piątek, 28 grudnia 2012

70-511 Rozdział 8 - implementacja IDataErrorInfo

Poprzednio zostały przedstawione reguły walidacji - ValidationRules. Mechanizm ten umożliwiał łatwe tworzenie reguł, według których były walidowane dane. Interfejs IDataErrorInfo implementujemy na poziomie obiektu. Dodaje to dodatkowy poziom walidacji - na poziomie poszczególnych obiektów.
Interfejs ten posiada dwie składowe:
  • Error - informacja o błędzie w obiekcie
  • Item - informacja o błędzie dla danego pola w klasie
Właściwość Error w większości przypadków nie jest implementowana (aby dostać jej wartość, należy bezpośrednio odwołać się do danego pola klasy). Składowa Item, integruje się z istniejącym systemem walidacji.

Po zaimplementowaniu interfejsu w obiekcie, należy włączyć powiadamianie o błędach w definicji bindowania (ValidatesOnDataErrors=True). Kolejnym elementem jest ustawienie właściwości UpdateSourceTrigger. Jeżeli będzie ona ustawiona na tryb PropertyChanged (walidacja po każdej zmianie wartości) może spowodować to duże obciążenie dla procesora. Jeżeli podczas walidacji wystąpi błąd, zostanie on dodany do kolekcji Validation.Errors. Aby go wyświetlić, możemy stworzyć odpowiedni styl dla kontrolki, w którym uwzględnimy sposób wyświetlania błędów.

Przykładowa implementacja z zastosowaniem w walidacji obiektu:

Code:
<Window x:Class="IDataErrorInfo_Implementation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:IDataErrorInfo_Implementation" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:Person x:Key="personObj"></local:Person>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
                                                    Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        
        <TextBlock>First Name:</TextBlock>
        <TextBox HorizontalAlignment="Left" VerticalAlignment="Center"
            Text="{Binding FirstName, UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}" 
            Grid.Column="1" Width="100"/>

        <TextBlock Grid.Row="1">Last Name:</TextBlock>
        <TextBox HorizontalAlignment="Left" VerticalAlignment="Center"
            Text="{Binding Source={StaticResource personObj}, Path=LastName, UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}" 
            Grid.Column="1" Width="100" Grid.Row="1"/>
    </Grid>
</Window>

Code:
using System.ComponentModel;

namespace IDataErrorInfo_Implementation
{
    public class Person : IDataErrorInfo, INotifyPropertyChanged
    {
        private int id;
        private string firstName;
        private string lastName;
        private string city;

        public int Id
        {
            get { return id; }
            set
            {
                if (value == id) return;
                id = value;
                OnPropertyChanged("Id");
            }
        }

        public string FirstName
        {
            get { return firstName; }
            set
            {
                if (value == firstName) return;
                firstName = value;
                OnPropertyChanged("FirstName");
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                if (value == lastName) return;
                lastName = value;
                OnPropertyChanged("LastName");
            }
        }

        public string City
        {
            get { return city; }
            set
            {
                if (value == city) return;
                city = value;
                OnPropertyChanged("City");
            }
        }

        public string this[string columnName]
        {
            get
            {
                string result = "";
                switch (columnName)
                {
                    case "FirstName":
                        if (!string.IsNullOrWhiteSpace(FirstName) && FirstName.Length < 3)
                        {
                            result = "First name must be specified";
                        }
                        break;
                    case "LastName":
                        if (string.IsNullOrWhiteSpace(LastName))
                        {
                            result = "Last name must be specified";
                        }
                        break;
                }

                return result;
            }
        }

        public string Error
        {
            get { throw new SystemNotImplementedException(); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}




Tworzony kod do pobrania: http://sdrv.ms/12GZQ0P

Brak komentarzy:

Prześlij komentarz