Infosys Microsoft Alliance and Solutions blog

« Are Remote MSMQ Queues Reliable? | Main | Debugging WPF Databinding errors »

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? :)

Baybuzskiy, Custom converter may come handy in this case. See an interesting example of it here - http://www.beacosta.com/blog/?p=29

Adding the following to the Style node gets rid of the error: TargetType='{x:Type TextBox}'

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.

how can we do the same for combobox?

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?

Nice one - but, how can one apply the red border, even if the TextBox is Focused / Hovered?

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Please key in the two words you see in the box to validate your identity as an authentic user and reduce spam.

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter