Ugrás a tartalomhoz

.NET Programming Technologies

Gergely Kovásznai, Csaba Biró

Eszterházy Károly College

Validation

Validation

As already mentioned in Section XIII.1, in the Binding.ValidationRules property one can specify rules for validating the source data of data binding. It is a usual validation task to check whether the user has filled all the mandatory textboxes in a form, i.e., none of the mandatory source data is empty. Of course, there also exist more complex validation tasks, e.g., checking whether a phone number is well-formed. Such tasks are supported by different subclasses of the ValidationRule class. We are going to introduce only one of them, called DataErrorValidationRule, and, additionally, the IDataErrorInfo interface. In the next example, we are going to show how to use them, but keep in mind that there are several different ways for realizing validation combined with data binding, c.f. corresponding literature!

Our (slightly unnatural) example: let us create a form on which users can register their own computers. They have to specify three pieces of data: the name of a computer (string), its age in years (double), and its IP address (string). The form should look like the one in Figure 3: around a textbox that contains incorrect data a red frame should appear, and a tooltip with an error message as well if the user drags the mouse pointer above the textbox.

XIII.3. Validation

First, we need to add a DataErrorValidationRule to each textboxes, as the next source code shows:

<TextBox>

        <Binding Path="IpAddress">

                <Binding.ValidationRules>

                        <DataErrorValidationRule/>

                </Binding.ValidationRules>

        </Binding>

</TextBox>

IpAddress referenced by the Binding is, obviously, a property of one of our own classes in the code behind. In order to make this own class “compatible” with DataErrorValidationRule, it must implement the IDataErrorInfo[4] interface. This interface declares an indexer, which receives as parameter the name of the property being validated and checks the value of this property. If the value turns out to be badly formed, then the indexer may return an error message; otherwise, it simply returns null.

public class Computer : IDataErrorInfo

{

        public string Name { get; set; }

        public double Age { get; set; }

        public string IpAddress { set; get; }

        public string this[string columnName]

        {

                get

                {

                        switch (columnName)

                        {

                                case "Name":

                                        if (string.IsNullOrEmpty(this.Name))

                                                return "Name must not be empty";

                                        break;

                                case "IpAddress":

                                        if (string.IsNullOrEmpty(this.IpAddress))

                                                return "IP address must not be empty";

                                        var parts = this.IpAddress.Split('.');

                                        if (parts.Length != 4)

                                                return "IP address must contain 4 numbers, separated by dots";

                                        foreach (string part in parts)

                                        {

                                                int intPart;

                                                if (!int.TryParse(part, out intPart)

                                                                                        || intPart < 0 || intPart > 255)

                                        return "IP address must contain integers, each between 0 and 255";

                                        }

                                        break;

                        }

                        return null;

                }

        }

}

As can be seen, validating the Name property only requires to check whether it is empty or it is not. The same check is needed to apply to IpAddress, but this is not sufficient only. IpAddress has to be splitted into several pieces by using dots as delimiters (string.Split), and then one has to check whether the number of the resulting pieces is four. Finally, one has to check whether each piece can be converted to an integer (int.tryParse), and whether its value is between 0 and 255.

Note that we have not specified any validation code for the Age property! In such cases, the default WPF validator is used, depending on the type of the given property (double): it checks whether the textbox is not empty and its content can be converted to double.

When running our current application, one can notice that while red frames appear around the badly formed textboxes, no error message pops up. The reason is that we need to make our textboxes capable to notice validation errors. A relatively easy way is to define a default style (Section XII.2) for textboxes, in which a trigger (Section X) is used to observe the Validation.HasError property of a textbox, whose bool value shows whether such an error has occurred. If it has, the trigger sets the ToolTip property of the textbox to the error message, and all of this can be realized in a slightly complicated way, as follows:

<Style TargetType="TextBox">

        <Style.Triggers>

                <Trigger Property="Validation.HasError" Value="true">

                        <Setter Property="ToolTip"

                                        Value="{Binding RelativeSource={x:Static RelativeSource.Self},

                                                                                        Path=(Validation.Errors)[0].ErrorContent}"/>

                </Trigger>

        </Style.Triggers>

</Style>



[4] The IDataErrorInfo interface can be found in the System.ComponentModel namespace.