I implemented type CustomDoubleConverter which implements IValueConverter.
I included it Converter={StaticResource customDoubleConverter} and corresponding resource in xaml-file.
It works fine.
The question is about error handling.
I would like to check if UI string represents correct double. if no then show one of two messages on label depending on invalid input: empty string or other non-double string.
Which approach should be used to show custom error messages on UI form when error happens during type converting from string?
I tried to do via exceptions, but received unhandled exception. Tip: Do not
throw an exception in a IValueConverter convinced me not to try exceptions any more.
I was able to check double after converting with correct handling of IDataErrorInfo interface in view model of MVVM. But it could be done after successful string to double conversion, which is not the case described above.
I have also ValidatesOnDataErrors="True" and ValidatesOnExceptions="True" for my text box.
I use MVVM approach for design if it is helpful (similar to the one described in WPF Apps With The Model-View-ViewModel Design Pattern).
In short:
I want to parse double from TextBox and show one of three error messages if any on UI label:
empty string (mentioned above),
invalid double string (mentioned above), and
negative number (does not mentioned above, but I handled it via IDataErrorInfo - it is not an issue).
It strictly depends on your UI design, or in other words, how you gonna notify about a problem to user.
I would say use of Dependency Properties. For example.
Let's say user inserts a value in TextBox. The TextBox has a DataError dependency string property. Converter in case of fail, simply sets that property to appropriate user string (can be recovered form localized resource). One time property setuppped, TextBox becomes red, clears content and prints out the error text generated by converter.
I mean the idea is use Dependency Properties, how it will end up in final UI depends on your app design and your choices.
There is also another related SO link :
How to handle exception in Value converter so that custom error message can be displayed
Hope this helps.
Related
I have a C1DataGrid with one column and I want to be able to validate the data when I commit a new row in the grid.
So far I tried to throw an exception in the setter of this property.
This validates the data while I am typing it in the text box correctly (throws an exception), but I am still able to commit the new row.
Furthermore I would like to only do the validation when I commit my new row and not after every new character I write.
Could someone show me how to do it? Many thanks!
You should implement inotifydataerrorinfo
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifydataerrorinfo?view=net-7.0
The easy way to do that is use the community mvvm toolkit
Inherit the viewmodel you're using for each item from Observablevalidator
Add your validation attribute(s), or custom validation
https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/observablevalidator
You could then check IsValid or HasErrors in the CommittingEdit event and stop it committing
https://www.grapecity.com/componentone/docs/wpf/online-datagrid/C1.WPF.DataGrid.4.5.2~C1.WPF.DataGrid.C1DataGrid~CommittingEdit_EV.html
The datagrid itself might automatically check HasErrors, I'm not familiar with C1Datagrid
Bear in mind that what inotifydataerrorinfo is doing is telling you your viewmodel has bad data in it. You then have to do something about it. Revert the change from a cached version or something.
It is because of this that I would usually keep any "original" OK data.
Have the user edit a copy of any item separately from that and then only replace that original item ( or add a new one to a collection ) if it is definitely valid.
With a datagrids where the user can just edit like it's excel, you're better stopping them actually entering any bad data.
I only use this for quite simplistic scenarios like only entering integers or some such. The way I handle that is with an attached behavior which will essentially just not let the user type or paste invalid data in. There are obvious inherent limitations to this approach.
Another thing to consider is a binding ValidationRule.
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-implement-binding-validation?view=netframeworkdesktop-4.8
These work as the user enters and will stop invalid data transferring to the viewmodel property. You still have bad data in the datagrid though. So the user types bad stuff, the cell should respond and turn red or whatever. But you still have your bad stuff there in your view.
I am using prism for windows 8 the BindableBase class to validate the properties, till now I can bind the string properties and validate them with custom validator.
Now I want to bind the double value directly to the view with two way binding.the problem is when user enters any alphabetical character then the setter of that double property doesn't gets fire cause its not a double value and might fires a conversion exception but because of that I cant validate my property.
may I go for the converter ?, but how can I raise validation exception and make the property invalid in converter
Does anyone know how to do this?
Two way binding a double does indeed give some issues in Windows Store apps (input validation, localization, ...). What I usually do is have another property that represents this double as a string and bind the string value. You can also add validation on this string property and check if it does parse to a double with double.TryParse().
Hopefully a better solution for Windoew 10 UWP will be announced in the near future to prevent the need for this hack.
i am new to WPF, I am trying to Validate some WPF controls i have been following this link WPF Binding Validations
and i have understood how they are doing it. but what i want is to have a common textblock showing error messages for all the controls, in the above link they use a separate textblock for each of the controls to view the error message, but i want to just change the border color of the control to red in case of the error and show the error messages in a textblock which is created to view the error messages for any of the textboxes that has the false input.
for example i have a textblock as
<TextBlock Name="txtError" Foreground="Red" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
so whenever the text of any textboxes changes and validation rule returns false i want the border of that textbox red and the message to be displayed in the above textblock.
Welcome to world of bindings, you can solve this issue by just making some more text boxes with bindings (as suggested in prev. answer) and have a style to show problem text box as red.
But I would suggest you to understand the concept of DataValidation and DataErrorInfo in wpf, on a quick search I think This is a good starting point, read about it its worth your time.
After you understand data error info, you can set data error template on your textbox to work around the red border requirement.
It is much easier if you implement either the IDataErrorInfo Interface or the INotifyDataErrorInfo Interface in your data model class. The first interface provides a string Error property and the second a GetErrors method that returns a collection of errors. You can then data bind these properties to either a TextBlock or an ItemsControl to display all errors that relate to an object.
Not wanting to duplicate the many online examples, I prefer to direct you to them instead. You can find help with implementing these interfaces in the How to: Implement Validation Logic on Custom Objects and How to implement INotifyDataErrorInfo in WPF 4.5? posts online.
Note that although the IDataErrorInfo interface was designed to deal with individual errors, you can alter it to deal with multiple errors if you add an Errors collection property. Take this example:
public string Error
{
get
{
StringBuilder errors = new StringBuilder();
foreach (string error in Errors) errors.AppendUniqueOnNewLineIfNotEmpty(error);
return errors.ToString();
}
}
public override ObservableCollection<string> Errors
{
get
{
errors = new ObservableCollection<string>();
errors.AddUniqueIfNotEmpty(this["Property1"]);
errors.AddUniqueIfNotEmpty(this["Property2"]);
errors.AddUniqueIfNotEmpty(this["PropertyN"]);
errors.AddRange(ExternalErrors);
return errors;
}
}
The AddUniqueIfNotEmpty method is just an extension helper method that I created which 'does what it says on the tin'.
If You are using MVVM - just create public property caled errorMessage and bind it to this textbox:
private string _emailMessage;
public string emailMessage
{
get
{
return _emailMessage;
}
set
{
_emailMessage = value;
OnPropertyChanged(emailMessage);
}
Now in xaml bind TextBlock.Text to this property:
<TextBlock Text="{Binding Path="emailMessage"} .../>
If You are using code-behind instead of MVVM You can just set Textblock.Text each time error has occured. Like below:
If(somethingBadHappened)
{
txtError.Text = "Some error text";
}
Hello search engine visitor. You may be feeling underwhelmed by the other answers to this question. There are two correct answers, depending on exactly what you mean by "all errors":
All binding errors within the current control
If you have multiple bindings to properties which may produce binding validation errors, the correct way to gather them together is to add a BindingGroup to your control. You can then query this object for all of the errors produced by the bindings it knows of. I won't go into detail about how to set this up; check Microsoft's documentation.
All INotifyDataErrorInfo errors in the data object
Perhaps you don't actually have any bindings to individual properties, because (for example) you are displaying an error message in a prompt and need to list all of the reasons why the user can't proceed.
You can abuse the GetErrors method to return all known errors when a null/empty string is passed, but this is a hack. You could also add a new property which returns all errors, but this means changing your data model and adding bespoke handling for the errors changing.
I have a better solution for you: DataErrorsControl. This is a custom control which:
Queries all properties of the ErrorSource object and flattens the resulting errors (with the help of CompositeCollection), then exposes that collection in read-only form as a CollectionView
Has an IsExpanded property which determines whether it displays all of the errors as a list, or just one error at a time on a single line
Supports asynchronous error generation, as required by the INotifyDataErrorInfo interface
Enjoy!
P.S. I also added support for navigating back/forward through the errors, but left the required buttons out of the default template to keep it simpler. You can add the UI or remove the command handlers per your requirements.
I have a form with a textbox bound to an integer, and a button. Now, when the value of the textbox is invalid, I want to immediately disable the button.
Normally, one would put a Can() method in the VM, and trigger a NotifyOfPropertyChange in the property's setter. However, if the user inputs a non numeric value for example, the textbox is invalid, but the property setter is never called, so I can't notify/disable the button.
So, how do I disable the button, when the user inputs an invalid value that doesn't cause the property setter to get called? My knowledge of CM is limited as I've just started out.
I've found the best approach to this problem is to make the property a string instead and do the necessary string to integer conversion in your property setter. If the conversion is invalid, then you could reset the TextBox value to a default value. This way your property setter will always get fired.
If your model has an integer property, then it makes sense to place the string version on the view model, as this is only really related to the UI, rather than business logic.
If you don't wish the user to be able to input non digit characters, then you can use a masked text box, such as the one included in the Extended WPF Toolkit, or in a third party control suite such as those offered by Telerik or Infragistics.
I'd use a MaskedTextBox instead and set the mask to integer only.
I used an application recently that was awe-inspiring. All the forms inherited from their own classes and a 'form' came with an amazing amount of functionality and looked the nuts.
What I'm interested in is this 'feature' of the form. This was a C# WinForms project and blew me away.
The forms were bound to objects that the group had written to support two-way data binding (to an extent). The way they behaved was pretty simple:
The data input forms all had controls that inherited from textbox and these were bound to properties of an object, Entering data immediately validated it and the box was a light pink if validation failed and a light green if it passed. If the box ever turns blue this actually means the value in the database the form is bound to has changed and your changes to the controls were immediately saved when valid values entered. It was the case that sometimes a section of controls had to be filled before a save occured. But it was all automatic. You could stop at any point and come back later and continue without actually saving yourself.
And like I say if someone else is editing the same record values they change caused your textboxes to become blue and you knew you needed to reload the screen to see up to date information.
All of this came from using their own form class they had written and their own textbox controls bound to an objects property.
I'm mainly wondering how the hell did the object figure out the value had been changed by someone else. It surely isn't polling the database. This system was amazing. The brilliance didn't stop there.
For simplicity. How might I create an object or collection of objects to mimic the bahaviour. I'm not going to but I can't even see how.
Thanks
I'm pretty sure that anything involving other people's changes would have needed to hit the database. For two-way binding, all you really need is change notification - i.e. INotifyPropertyChanged (or a FooChanged event for every Foo property). This is all abstracted into TypeDescriptor - i.e. any binding that uses the regular PropertyDescriptor implementation (which it should) will know about notifications via SupportsChangeEvents, AddValueChanged and RemoveValueChanged.
For validation - IDataErrorInfo is your friend; by implementing this, you can volunteer validation information (which is used and displayed by several controls, such as DataGridView). i.e.
IDataErrorInfo dei = obj as IDataErrorInfo;
if(dei != null) { // supports validation
string err = dei["PropName"]; // or .Error for overall status
bool clean = string.IsNullOrEmpty(err);
}
Note that an alternative approach would be to have a Color property on the data aobject, and bind that directly to the textbox etc.