Exception (validation) handling in WPF DataGrid - wpf

If the binding engine cannot convert the entered text into the bound property's data type in a DataGridTextColumn (binding below), the cell gets a red border, and you cannot edit any other cells until the error is fixed. The border remains even if you tab out of the cell.
<DataGridTextColumn Binding="{Binding IntegerProperty, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnExceptions=True}" />
This is all great in my setup. The problem is that if I throw an exception in a property setter, the behavior is different. First the red border (validation error) is removed immediately when I tab out from the cell and I can continue to edit the rest of the grid's cells.
Is there any way to make the exception thrown in property setter behave similarly as the binding engine's way of handling FormatExceptions? The biggest annoyance is that the validation error is removed after moving out from the cell.

I think you should NOT throw an exception in a property setter.
Take control of the validation by creating your own ValidationRules objects.
This might help you or you might be beyond this.
http://www.wpfsharp.com/2012/02/03/how-to-disable-a-button-on-textbox-validationerrors-in-wpf/
When the exception is in the UI, the invalid value is not even passed through to the bound property.
Also, you can handle the exception instead of just throwing it and set the property to a default value or clear it out or something.

There's nothing wrong with throwing an exception in a setter. After all, some setters call validation or other procedures while they're being set. For example, I may have a Connected property for a database that attempts to open a database connection when set to true. This could be set to a toggle button on my wpf window. That said, you could create a listener--something similar to this link: http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors.
In my case, I'm using MVVM and Prism/Unity framework. Once I retrieve the value and either trap an exception or raise one, I call an internal event within my View Model called NotifyViewOfException. I pass in the exception object and it handles it from there by displaying a window. You don't have to use Prism/Unity to do this. Based on your description, I don't know what you're using so I won't go into detail about that piece of it.

Related

WPF DataGrid validation when bound to a DataView

I am attempting to validate input on a DataGrid which is populated by a DataView (e.g. myDataGrid.ItemsSource = myDataView). However, all the WPF DataGrid validation examples I have seen assume that the DataGrid source is a C# class. I can't figure out how to hook up a single cell (i.e. a column) to a code-behind validation. Can someone give an example or point me to one?
Ok, I did some quick tests; I think the main impediment to really doing it manually is that the DataGridCell doesn't create any bindings for its content when assigning directly a DataView for display. However, if you're willing to jump through the hoops of assigning custom DataGridTemplateColumns when creating the DataGrid, you can access the bindings on, say, the TextBox instances inside the template, and set custom validation errors on them.
Well actually, either this or override the default style of the textboxes generated by the DataGrid; you see, the default textbox style doesn't have any borders or anything, so setting a validation error on it doesn't have any effect. Making it into a normal textbox with DataTemplate or overriding its style would enable you to actually make something visible as an effect of setting the validation error.
However you'll need to do some research by yourself; I did a quick prototype and it works, but I can't create the binding correctly in the DataTemplate (either I forgot all the WPF I knew since I worked with it last, or I only know how to work with proper bindings :)). If you get somewhere with that it's easier going forward:
Somehow get access to a BindingExpression; what I did was attach a handler to the LostFocus event and checking if what lost focus was a textbox that was inside a DataGridCell; if so, I simply mark that binding as invalid (with t representing a TextBox instance):
var x = t.GetBindingExpression(TextBox.TextProperty);
Validation.MarkInvalid(x, new ValidationError(new ExceptionValidationRule(), x.ParentBinding, "error", new Exception("error")));
I must confess I'm not sure anymore what each argument's role is in the ValidationError constructor is (I think the exception message is displayed by default in the validation tooltip? Or is it the error content?), but I'm sure you can figure it out. Now if you don't mind, I think I'll take a break... like I said, it's not easy going against the flow :)
So I did some more research, and what I was basically missing was that I can specify the column name with the Path attribute of a Binding (or even use the column ordinal in brackets, e.g. Path="[0]"). After that realization, everything is basically the same as using a class property. So a typical DataGrid column definition I use follows:
<DataGridTextColumn Header="Regular" EditingElementStyle="{StaticResource ValidationErrorStyleBoxRA}" ElementStyle="{StaticResource ValidationErrorStyleBlockRA}" Width="60">
<DataGridTextColumn.Binding>
<Binding Path="HourlyRate" StringFormat="F3" ValidatesOnExceptions="True" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:HourlyRatesAmountValidate ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>

WPF .net 4.0: Textbox resets caret position when binding with UpdateSourceTrigger=PropertyChanged

I've got the following Situation:
TextBox which is bound to a property:
<TextBox Text="{Binding Settings.ClientName, UpdateSourceTrigger=PropertyChanged}"/>
The property ClientName stores its value in the unterlying structures and does NOT call Notifyon the property changed event. instead the underlying structures send an event to refresh the UI after they processed the value . If such an event is fired, the ClientNameProperty is set correctly and Notify is called for this property.
the problem is that if i enter any text, the caret seems to jump to the first position in the textbox, actuall reversing any string i enter. "abcd" becomes "dcba"
I noticed that this behaviour occured after we migrated to Net 4.0.
Are there any good solutions out there?
Many thanks
There is no built-in behavior that would do that. That problem is likely to come from your processing.
On a side note, if you want the TextBox to change from code-behind as well as from user input, you want to make it Two-Way:
<TextBox Text="{Binding Settings.ClientName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
EDIT:
You could also make the ClientName a dependency property (propdp snippet in vs2010). That would automatically fully support binding(/styling/animation), and gives you the possibility to act when the value changes as well as to coerce it back through callback delegates.
Last but not least, you still wouldn't need your Settings class to implement INotifyPropertyChanged.
Here is a place to start (msdn).
I suspect you are suffering from this behavior change in the WPF TextBox: https://connect.microsoft.com/VisualStudio/feedback/details/588343/changed-behaviour-from-net-3-5-to-net-4-0-of-wpf-textbox-formatting-when-propertychanged-is-used-as-updatesourcetrigger (Changed behaviour from .Net 3.5 to .Net 4.0 of WPF TextBox formatting when PropertyChanged is used as UpdateSourceTrigger)

DataBinding happens only first time

I have two User Controls in my window, both are bound to the same context.
One of them is getting updated and the other is not.
What could be the reason?
Sounds like you have an issue with the bindings. Make sure your dependency properties bound to each control are both getting notified via OnPropertyChanged. If both properties aren't getting notified this would be your issue regardless if they share the same datacontext (viewmodel).
Blessings,
Jeff
Beware of UserControls by default they bind one way you have to specify TwoWay:
<Binding Mode="TwoWay" ...>
...
</Binding>
Do you see any binding errors in the Output window? If so you can post that and maybe we can understand.
If not try to put a dummy converter in the binding and see if its methods are hit.
One from the multiple issues could be binding source address is changed.
Without seeing the code, we only guess:
Check that the property names in the bindings are an exact match (including case). It is quite common to have typing errors that cause bindings to fail (silently).

Validation ErrorTemplate not showing on data errors

This is a bit of a WPF whodunnit! My validation temples it not appearing when expected
The Problem
Basically, I am using IDataErrorInfo on my view model to provide feedback on data entry errors. I can see this being called and working as expected, but the validation error template for the bound control is never displayed by WPF!
I have tried both using the built-in default textbox red border error template, a style error template, and a hard coded template. None of these are displayed in a data error situation.
Heres my xaml binding code:
<TextBox x:Name="txtCaseNumber"
Text="{Binding Path=CaseNumber, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>
Wierdly, the error gets into the Validation.Errors collection. The follow code results in my IDataErrorInfo error message getting displayed next to the bound control. This leads me to think the problem is on the xaml side, rather the viewmodel side.
<ContentPresenter
Content="{Binding ElementName=txtCaseNumber, Path=(Validation.Errors).CurrentItem}" />
Additionally,
System.Windows.Controls.Validation.GetHasError(txtCaseNumber) returns true.
I am hosting WPF in winforms if that makes a difference. I can't find any references in my code or styles to Validation or ErrorTemplate so I'm pretty sure this isn't a styling own goal.
Cracked it.
The ErrorTemplate attached property uses the adorner layer to show error templates on data validation failures reported via IDataErrorInfo. The Adorner layer is not always available for all controls in all situations. Your control or one of its parents needs to explicitly provide one.
The default Window control template contains an AdornerDecorator which enables the adorner layer for its children. This why my other window showed my error templates just fine, because this window used the default control template
The window which didn't show my error template had used a style which provided a ControlTemplate for my window. This control template did not provide an <AdornerDecorator>, hence no adorner layer to show my error template.
The fix was as simple as wrapping my window control template with <AdornerDecorator>.

WPF lengthy Validation Scenario

in my scenario I have a Linq2SQL Data backend.
my Dataobjects implement IDataErrorInfo to catch errors like Name==null (fast to execute Validationrules that only require the value, nothing special so far )
the Dataobjects are organized in a tree-structure, so each has a Parent and Children
How can I validate if a chosen Name is Unique under the Children of a Dataobjects' Parent?
The problem I'm facing is, that the unique Name validation requires a Database roundtrip which lags typing if UpdateSourceTrigger="PropertyChanged" on the TextBox binding to the Name.
On the other hand, I could set UpdateSourceTrigger="LostFocus", but the problem with that is, that I enable/disable a "Save" button on valid/invalid data. Now in the invalid state you can't click the Save button, so there's no way the Textbox could lose Focus to update (only tabbing away which is ugly, but there are more "unusabilities" with LostFocus (e.g. Error keeps displaying while typing and thus changing the name).
what would be ideal was a way to say for individual validationrules to apply on different events like so:
<TextBox Grid.Column="1">
<TextBox.Text>
<Binding Path="Foldername">
<Binding.ValidationRules>
<wpfresources:UniqueChildValidationRule ValidationStep="UpdatedValue" **UpdateSourceTrigger="LostFocus"**>
... stuff here ...
</wpfresources:UniqueChildValidationRule>
<DataErrorValidationRule **UpdateSourceTrigger="PropertyChanged"**/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
What is the best way to solve this?
EDIT
This MSDN article seems to suggest, that a BindingGroup would be the way to go. I'll look into that...
I finally figured a way to accomplish what I wanted.
The use of BindingGroup worked, but I stripped my solution down because what I needed essentially was a way to show a Validationerror in the correct Textbox.
I did so now with an attached property that I read out on execution of the "save"-functionality. then I manually validate and set a ValidationError on the textbox. that way the textbox can keep its PropertyChanged UpdateSourceTrigger and the lengthy validation is done on submit.
For what it's worth, validation that requires potentially arbitrary time (talking to a database over a network, e.g.) is one form of validation that does not need to be reflected in the UI in realtime. If you can work it so that it is (pre-caching the values that will be checked by reading them from the DB before you need them, e.g.), so much the better, but this is the one scenario where reporting an error after the user has submitted the data is generally acceptable as long as you don't destroy the information that the user entered.

Resources