Bind textbox text to disk path of xml file - wpf

I have a window set up that shows the data in an xml file and allows the user to change it, save, etc. I have pretty much evertything set up except that I would like to have a textbox or textblock that shows the file path of the current file that the user is working with.
I have an XmlDataProvider set up called 'xmlData' and I have the text binding as follows:
Text="{Binding Path=Source, Source={StaticResource xmlData}}"
I have also tried the datacontext to the static resource above and both just give me a blank textbox even though I know there is an xml file in the data provider (I can write to it). Am I missing something or can this not be done this way?

The problem is that XmlDataProvider.Source is a Uri not a string. So you will want to do something like:
Text="{Binding Path=Source.AbsolutePath, Source={StaticResource xmlData}}"
Absolute path isn't going to give you something like: C:\My documents\test.xml however, it's more likely to be something like: file://c:/my documents/test.xml. So you'll need to find a good way to manipulate the source Uri to get what you want.
One thing you could do is use a Converter to parse it and return what you want.
It looks like Uri.LocalPath might also give you what you want, but I'm not 100% sure without testing it.

Ok well I figured something out that works but it's not what I wanted. I ended up going 'old school' with it. I put a standard property on my form in the code behind with a backing variable and get/set methods. In the set method I just set the text property to the same value as the backing variable.
I'm waiting to mark this as the answer to see if someone has a better solution.
--What I tried--
After the above answer/conversation I tried sticking a converter in that simply returned the value back so that I could break into it in the debugger and see what was being passed to the converter. No matter what I did I couldn't get it to hit the breakpoint so it seems like it wasn't even getting to the converter for some reason.
I then tried to define a dependency property on the code behind of the form itself and a standard property as a wrapper (where the get and set just use the GetValue and SetValue on the dependency property) and bind the textbox text to that using relativesource and findancestor. Basically I bound the text to that property of the form. Then I changed the property using the wrapper in code behind whenever the user browsed for a new file. This worked on the load up, but whenever I set the value in code it didn't update the text in the textbox. I even set the binding tracing to high using diagnostics; I saw that it found the form and said it bound to the value, etc. but whenever I hit the browse method and change the path I get no output and no change in the text.
Like I said, what I have is working and it's reasonable I guess, but if anyone can add insight as to why this wouldn't work I would be very interested to know. I am fairly new to WPF so I want to learn to do these things right...

Related

Powershell WPF checkbox binding

I have a MenuItem Checkbox in my main window as well as in another two windows:
<MenuItem x:Name = 'FileMenu' Header = '_File'>
<MenuItem x:Name = 'EnableAutostart' Header = '_Enable Autostart' IsChecked="{Binding AutoStart, Mode= TwoWay}" IsCheckable="true" ToolTip = 'Enables the autostart.' InputGestureText ='Ctrl+S'></MenuItem>
I use it to define whether or not the script automatically starts on user logon (a function checks for the scheduled activity and sets the checkbox accordingly) and when clicked it enables or disables it.
Now what if I want to keep all the 3 different windows checkboxes synced?
I read a lot about binding but can't really get it working, I tried to set the binding on a bool "Autostart" and to set it true before showing the window but it does nothing at all.
How can I define a bool in my code and make it so that, whenever I change that bool, it reflects on all the menuitems checkboxes bound to it? (even if the other windows are yet to be created/shown)
I read about needing to make it a property... can I just make a class, set a property to it called something like "AutoStart" and it would work?
Thank you #bluuf, you kind of gave me a hint.
Anyway comes out i actually achieved to do a databind previously in my many tests but as you said, the INotifyPropertyChanged is not so easy to handle in powershell, or maybe it is?
Good guy Trevor Jones (link at bottom) explained an easy way and i did the last steps to understand it and apply it to my code. Thank you Trevor.
He basically explains that this one collection:
System.Collections.ObjectModel.ObservableCollection[Object]
Has an already implemented iNotifyPropertyChanged that works well in powershell, without adding c# classes.
You just create that collection, add your bool to it, and point the binding.source to it.
Trevor's article, actually read it, worth your time:
https://smsagent.blog/2017/02/03/powershell-deepdive-wpf-data-binding-and-inotifypropertychanged/
P.S. Trevor also points to this article which explains how to implement the c# class (and more), if anyone is interested:
https://www.ephingadmin.com/better-know-a-powershell-ui-50-shades-of-bindings-part-1/

Using the namespace that is in XAML in the source code

From this document:
http://www.telerik.com/help/silverlight/radmaskedinput-features-extensions.html
I am interested in <telerik:RadMaskedNumericInput maskedInput:MaskedInputExtensions.Maximum="1000" />
But in their examples they are setting a property like MaskedInputExtensions.Maximum directly in the XAML. So if I want to use it I have to go to go to all my XAML files and set it there.
But since I have created my own control so I have both a CS source code for it and also my own XAML for the style of my control.
Is there a way I can set it in either of those places to make it more reusable?
The best way to do it is using styles.
Check this out.
http://blogs.msdn.com/b/pakistan/archive/2013/03/07/xaml-how-to-style.aspx
http://www.codeproject.com/Articles/180656/Styles-in-Silverlight
It means that you have a pre-defined style for every element of a certain type, so if you want to change the same property for every element of that kind you just change this specific style.
If this is not what you want you can also create a property called "Maximum" for example and bind it to your controls manually. Once you change this property it will reflect on your controls.
Hope it helps!!

Getting the current culture date pattern in XAML code

So in my (large) project, I've got a special date box that derives from a masked text box and thus has a "Format" property. It works by giving it a short date format, such as:
<extended:DateMaskTextBox Format="yyyy-MM-dd" />
Now at the start of the application, the ShortDatePattern property of the CultureInfo.CurrentCulture.DateTimeFormat object is set, depending on some logic. I would like to obtain this ShortDatePattern to use it as a value for my Format property of my DateMaskTextBox.
So far I've got this, and it is not working:
<extended:DateMaskTextBox Format="{Binding Source={x:Static glob:CultureInfo.CurrentCulture}, Path=DateTimeFormat.ShortDatePattern}" />
Any idea why this does not work? Thanks.
That Binding syntax is correct and should work just fine. Are you getting any binding errors in your output window? Have you tried displaying that same Binding on a TextBlock.Text in place of your control to just see if the string is coming through?
Without seeing its code I can't tell but I suspect that the problem may be with the DateMaskTextBox rather than the Binding. If the control is not set up correctly to respect newly set values of its Format property the bound value may not be getting used at all or be getting used too late to affect the behavior you're seeing when interacting with the control.

Data binding: Different triggers for different purposes

I have a WPF MVVM data form window with data validation. A lot of the controls are text boxes. Currently, the data binding trigger is set to the default, i. e. loss of focus. This means that a field is only validated when it is likely to be filled out completely. So when deleting a number and typing another number, the transient empty value will not be displayed as input error.
But a drawback is that the Save button can only be enabled when the focus moves out of the text box. (No matter where, just out of the edited control. Assuming there is anything else focusable.) If this is the only change, the user waits for the Save button to be available and nothing happens. For the Save button, I'd like to use an immediate binding trigger. How can that be done?
Edit: Forgot to mention that my Save button (which uses ICommand) is only enabled when the input is determined modified and valid. So the data will remain unmodified until data binding updates it, and that won't happen until the focus moves to another control.
I actually had a similar question a while back and the solution I ended using was a custom DependencyProperty that kicked off a timer when a key was pressed, and only actually processed the PropertyChange notification if a specific time had passed.
This means the bound property doesn't get updated (and validated) unless the user pauses in typing for a set period of times.
The code can be found here (may need a bit of cleanup), and it is used like this:
<TextBox
local:DelayedUpdateBehavior.TargetProperty="{x:Static TextBox.TextProperty}"
local:DelayedUpdateBehavior.Milliseconds="1000"
Text="{Binding MyTextProperty, UpdateSourceTrigger=Explicit}" />
Edit: Actually this link might be better. It's a markup extension so you can use it directly from your binding. I can't remember which of these two methods I used in the past, but I know it was one of them :)
<TextBox Text="{local:DelayBinding Path=MyTextProperty, Delay='00:00:01'}" />
Assuming you're using an ICommand type interface for the button click event:
You can...Implement string properties with INotifyPropertyChanged and bind them to your textbox controls. Now in your Command canexecute method you can check to see if the property is !nullorempty.
e/ grammar
Set your Binding's UpdateSourceTrigger property to PropertyChanged. The default for TextBoxes is LostFocus.
Update: So you want to have data binding working on your TextBox and only allow numbers? Have a look at this question: Create WPF TextBox that accepts only numbers
Or use a converter and bind the Save button's IsEnabled property to your TextBox (maybe using a MultiBinding if there's more than one), and use a converter which determines if the text is a valid number and returns true or false.

Silverlight errors in data formats on binding

I'm trying to take care with every possible error when a property gets its value through a Binding (MVVM) like being out of a given range.
This is working perfect by using "ValidatesOnDataErrors" in the control I want to check.
The problem comes when I try to check if the given value is accepted by that property in the modelView.
For example, when I write "june" in a DateTimePicker control the binding is broken (the property is a DateTime) so it never gets its value and I can't control the errors the same way I do with the rest of rules.
How should I try this? Is there any solution?
Thanks in advance!!
Solution was really simple!!
If you have a DateTime property binded to a textbox, it's enought to set "ValidatesOnExceptions=True" on Binding instruction from XAML.
If you just want to parse this by youself, you have to use ValidatesOnDataErrors=True and make a validation function to raise a message.

Resources