I'm having this really simple class, lets call it Customer. It look like this:
namespace TestValidation { class Customer { private string _name; public string Name { get { return _name; } set { _name = value; if (String.IsNullOrEmpty(value)) { throw new Exception("Customer name is mandatory."); } } } } }
Now, I've created a basic form, where the user can add customers to the database. The form contain simple TextBox, bounded to the Name property of Customer, and an "Add" button.
The XAML code is:
<Window x:Class="TestValidation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TestValidation" Title="MainWindow" Height="350" Width="525"> <Grid> <TextBox Margin="119,86,107,194" Name="CustomerName" Text="{Binding Path=Customer.Name, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}" /> <Button Content="Add" HorizontalAlignment="Left" Margin="204,176,0,0" VerticalAlignment="Top" Width="74"/> </Grid> </Window>
From the setter of the Name property, you can understand that the name is mandatory for me, so I want an validation event to rise if the Name TextBox left blank. By validation rules of WPF - once the user focus out of the textbox, and there's no value over there - it should change the border color to red. For some reason - this is not happening, and I don't have a clue why. What is wrong in my process?
Now, I've read so many good articles about Validation in WPF (like Enforcing Complex Business Data Rules with WPF, Data validation in WPF and Validation in Windows Presentation Foundation), but none of them helped me solving my problem.
Eventually, I want the form to look like the form in Brian Noyes excellent article over the first link (Don't have 10 credits, so I can't attach a photo... sorry).
I'll be grateful if someone can explain to me how it really works.
Important note - I'm working with .Net framework 4, so I need a solution that suits this version.
User data warrants verification in just about every application containing these forms. In all likelihood, if you have experience working with WPF application forms, you’ve had to deal with the implementation of validation in some capacity. In spite of the large number of choices on hand, most of them are developed to function at a “field level.”
For some reason everything in WPF is soo complicated! I can do the validation in 1 line of code in ASP.NET which requires like 10-20 lines of code in WPF!!
The Binding class in the WPF API has a property called ValidationRules which you can use to associate your validation rules with Binding or MultiBinding objects. To specify the value for this property, you can either derive from the ValidationRule class or use one of the following built-in classes: DataErrorValidationRule.
Here is a very simple form in XAML that is created which has three textbox controls: Let us add code so that when values are entered in the above text boxes, they automatically run validation and if there are validation errors, they will be displayed next to the corresponding control. In order to do this, the following two steps are needed:
I would definitely recommend using IDataErrorInfo for WPF validation since WPF already understands how to use it, and its easy to implement.
To start with, add the interface to the class containing the data you want to validate. The required methods will probably look something like this:
public class Customer : IDataErrorInfo { ... #region IDataErrorInfo Members string IDataErrorInfo.Error { get { return null; } } string IDataErrorInfo.this[string columnName] { get { if (columnName == "Name") { // Validate property and return a string if there is an error if (string.IsNullOrEmpty(Name)) return "Name is Required"; } // If there's no error, null gets returned return null; } } #endregion }
Next, you need to set ValidatesOnDataErrors=True
in your TextBox binding so it runs the validation whenever the Name
property changes:
<TextBox Text="{Binding Path=Customer.Name, ValidatesOnDataErrors=True}" ... />
And finally, create a Validation Template in your XAML to tell WPF how to draw a validation error. Here's the style/template I usually use:
<!-- ValidatingControl Style --> <Style TargetType="{x:Type FrameworkElement}" x:Key="ValidatingControl"> <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" /> </Trigger> </Style.Triggers> </Style>
Also, be sure your Customer
class implements INotifyPropertyChanged
so it correctly responds to UI updates. I don't see that in your code, but often people leave that out for simplicity :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With