Getting the current culture date pattern in XAML code - wpf

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.

Related

IValueConverter with error handling

I know this is a pretty broad problem, so I'm surprised I haven't found a good answer yet. Here's my situation:
I have a class named TimeConverter that I use quite often, which implements the IValueConverter interface converts a string containing an amount of time (such as "25:36") into an integer representing the number of minutes (which for the earlier example would be 1536). Currently, when someone enters something untranslatable (like "asdf") the converter returns DependencyProperty.UnsetValue, which causes the bound element (usually a TextBox) to show a red border. Here's the problem, the class containing the integer property on the other end of the binding needs to know that there is a conversion error.
I've found this to be quite difficult and almost impossible to do without the data item having a reference to the bound TextBox. If I get a reference to the TextBox, I can use the Validation attached properties, but i feel like that's sloppy and its also not always possible. Currently I have one of these bindings in place on a TextBox, inside a Setter, inside a Style, inside a DataTemplate (pretty far removed from the visual tree), which also prevents me from using the Validation.Error even for notification. And of course the simple answer of binding Validation.HasError to the data item doesn't work because of how the property is declared.
So how CAN I notify the data item when the conversion fails?

Bind textbox text to disk path of xml file

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...

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.

Is this a crazy way to handle multi Validation types with IDataError and WPF?

We are using the standard method for our controls to report broken BO rules. This is done via the interface IDataError in our BO’s and in XAML the control is bound to the BO’s property etc. This approach works OK. But we need to show 2 types of visuals in the UI depending on the type (or category if you like) of the invalidation error. If it’s a required field then we show a CueBanner (water mark) but for other types we change the colour of the controls boarder. In both scenarios we set the tool type of the error message.
The Problem with IDataError is that it doesn’t support a method/property to distinguish between error types.
The only way I can do that is by examining the error text, required field text must contain the key word “required”. The following approach doesn’t feel right but it’s the only way I can determine the type of error and then deal with it accordingly. All required field rules must have as part of the error text “required field”.
To make this all work I have created a custom dependency property called ErrorMessage. In my ResourceDictionary I have a Style.Trigger for Validation.HasError. In there I set my dependency properties value to the ErrorContent. Now when my dependency properties value changes I can examine the text and set the Validation.SetErrorTemplate( myControl, newErrorTemplate) to the template to suit the error type. I have to wire up a few events to the control such as lost and got focus to manage removing or adding the cueBanner template but the whole thing will work. It’s just that I’m not sure it’s the best way to do it.
PS. When I set the ErrorTemplate i’m doing this in code, thats building and adding it. Is there a way to point Validation.SetErrorTemplate to a static resource keeping in mind that I need to switch between at least 2 types?
Your thoughts please..
Would it be possible to derive an interface IDataError that adds an extra property which is an enumeration of the error type. Then you could try and bind against it.
If you're okay with an (untested)approach that suffers a little bit of clarity, then you could do the following:
throw an exception instead of returning an string with the IDataErrorInfo Interface. In your ErrorTemplate, you can access the ValidationErrors (and the ValidationError.Exception Property).
Then, you use a DataTrigger on the Exception in combination with a converter, that checks for the right Exception-Type and return true or false. It should be enough to do the job.

Resources