Required Field Validation in WPF
In my earlier blog on user input validation in WPF, I had discussed about how extension methods can be used to provide for custom valiation logic. If your need is more simply only mandatory fields, a validation that the RequiredFieldValidation control provides in ASP.NET, you could very well use the concept of Data triggers in WPF.
One of the key benefits triggers offer is that they can be effectively managed within the XAML without usually requiring much of procedural code. Also since triggers are raised on specific actions/events, they are automatically undone when the action/event is over. This comes handy and saves code, since otherwise in procedural code, you need to handle both cases (something that is seen in my work with extension methods).
So if you have a need of say TextBox controls that should not be empty and should contain some value, you can create a Style with a Data trigger that fires when the TextBox's Text field is empty. The style will look something like below
<Style x:Key="requiredFieldValidationStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter Property="TextBox.BorderBrush" Value="{StaticResource FaultyBorderBrush}" />
<Setter Property="TextBox.ToolTip" Value="Input value is mandatory" />
</DataTrigger>
</Style.Triggers>
</Style>
Note how the trigger uses RelativeSource to bind back to it's own Text Property. If the Value of the property is an empty string (""), the BorderBrush is set appropriately to show a red border and a ToolTip is also attached to indicate what the error is. The BorderBush uses another local brush resource, which I defined as below
<LinearGradientBrush x:Uid="LinearGradientBrush_1" x:Key="FaultyBorderBrush" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
<GradientStop x:Uid="GradientStop_1" Color="#FFABADB3" Offset="0.05"/>
<GradientStop x:Uid="GradientStop_2" Color="#FFE2E3EA" Offset="0.07"/>
<GradientStop x:Uid="GradientStop_3" Color="#FFFF0000" Offset="1"/>
</LinearGradientBrush>
Finally this Style can be applied to a TextBox and it will fire at run time based on the Text property of the TextBox
<TextBox Style="{StaticResource requiredFieldValidationStyle}" />
A few things to remember
1. The Style created can be applied to any control. It will however not work for controls that don't expose a Text Property.
2. When the above style is added to the XAML, VS designer gives an error - "Value 'TextBox.ToolTip' cannot be assigned to property 'Property'. 'ToolTipService' type does not have a matching DependencyObjectType" and doesn't load the design view. The XAML loads properly in Expression Blend though. I am trying to figure out a fix for this. The code will however compile, build and execute without issues.
3. Another way to address the Style is to use the TargetType and set it to TextBox. This way the Style will be used for any TextBox on the XAML and you don't need to set it explicitly. The TextBox qualifiers from the Property names will also go away. The Style will look like the following
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter Property="BorderBrush" Value="{StaticResource FaultyBorderBrush}" />
<Setter Property="ToolTip" Value="Input value is mandatory" />
</DataTrigger>
</Style.Triggers>
</Style>
Another side benefit of this is that the VS designer works properly with this syntax.
4. The Style is only a visual indicator. In the code, you will still need to check the TextBox.Text for it being empty or not as part of your validation logic.
This hence, essentially gives you a pure XAML based visual representation for required field validation using the Data triggers.
Comments
Nice solution, but, does WPF provide any way to implement own comparsion type between expected and bound value?
For example, how i can extended implementation of DataTrigger? :)
Posted by: Baybuzskiy Artem | February 19, 2008 12:56 PM
Baybuzskiy, Custom converter may come handy in this case. See an interesting example of it here - http://www.beacosta.com/blog/?p=29
Posted by: Atul Gupta | February 22, 2008 10:33 AM
Adding the following to the Style node gets rid of the error: TargetType='{x:Type TextBox}'
Posted by: RMEscobar | September 30, 2008 3:31 AM
RMEscobar, which error are you talking about? Adding the target type to style is not necessary. As I have explained earlier, if you do that, the style will apply to all TextBox on the window (if this is window level style).
If not using the target type, the property names however need to be qualified with the control type as well like TextBox.BorderBrush, else you will get an error since the property cannot be resolved.
Posted by: Atul Gupta | September 30, 2008 4:45 AM
how can we do the same for combobox?
Posted by: jothi | March 23, 2010 9:22 PM
I would like to know what should be the Value in the Data Trigger be if we have to validate a Email ID. Can we give regex in the value field?
Posted by: Sreedevi | September 20, 2010 6:31 AM
Nice one - but, how can one apply the red border, even if the TextBox is Focused / Hovered?
Posted by: Daniel | January 23, 2013 9:32 PM
Looks good.
Can we change the style to display Required field validation image (Red Box X) like ASp.net in the textbox?
Posted by: Pramod | May 30, 2017 10:54 AM