首页 > 解决方案 > WPF 使用 IDataErrorInfo 验证子类属性

问题描述

给定下一个示例:

模型

public class ProjecteModel : ObservableObject, IProjecteModel
{
    private string _patientID

    public string IdPacient
    {
        get => _idPacient;
        set
        {
            _idPacient = value;
            OnPropertyChanged(nameof(IdPacient));
        }
    }

    /* More fields here... */
}

其中 ObservableObject 是实现 INotifyPropertyChanged 接口的基类。

视图模型

public class ProjecteViewModel : BaseViewModel, IDataErrorInfo
{
    private IProjecteModel _projecte = new ProjecteModel();
    private string _codiClient;

    public IProjecteModel Projecte
    {
        get => _projecte;
        set
        {
            _projecte = value;
            OnPropertyChanged(nameof(Projecte));
        }
    }

    public string CodiClient
    {
        get => _codiClient;
        set 
        { 
            _codiClient = value;
            OnPropertyChanged(nameof(CodiClient));
        }
    }

    public string this[string columnName]
    {
        get
        {
            string msg = String.Empty;
            switch (columnName)
            {
                case "CodiClient":
                    if (CodiClient.Length <= 0)
                    {
                        msg = "ID Client is required.";
                    }
                    break;

                case "IdPacient":
                //case "Projecte.IdPacient":
                    if (Projecte.IdPacient.Length <= 0)
                    {
                        msg = "Id Pacient is required.";
                    }
                    break;
            };

            return msg;
        }
    }
}

看法

    <!-- Id Pacient -->
    <StackPanel Orientation="Vertical" 
                Width="{Binding ElementName=capComandes, Path=ItemsWidth}">
        <TextBlock Text="ID Pacient:" 
                    Style="{StaticResource FieldNameTextBlock}"/>
        <TextBox x:Name="IdPacient"
                    Width="150" 
                    HorizontalAlignment="Left"
                    Margin="0, 0, 0, 15"
                    Foreground="{StaticResource ForegroundFieldValuesBrush}"
                    Text="{Binding Projecte.IdPacient, 
                                   Mode=TwoWay, 
                                   UpdateSourceTrigger=PropertyChanged, 
                                   ValidatesOnDataErrors=True}"/>
    </StackPanel>

    <!-- CodiClient -->
    <StackPanel Orientation="Vertical" 
                Width="{Binding ElementName=capComandes, Path=ItemsWidth}">
        <TextBlock Text="ID Client:" 
                   Style="{StaticResource FieldNameTextBlock}"/>
        <TextBox x:Name="IdClient"
                 Width="150" 
                 HorizontalAlignment="Left"
                 Foreground="{StaticResource ForegroundFieldValuesBrush}"
                 Text="{Binding CodiClient, 
                                Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged, 
                                ValidatesOnDataErrors=True}">
                        </TextBox>
    </StackPanel>

验证适用于 CodiClient,但不适用于 IdPacient。

验证方法:public string this[string columnName]从不为 IdPacient 调用。

如何验证子类属性?

标签: wpfvalidation

解决方案


IDataErrorInfo需要在包含您绑定到的属性的任何类中实现。

看看我的博客文章,我的基础可绑定对象类实现了 IDataErrorInfo,并包含一个从属性ValidatePropety()调用的虚拟方法。public string this[string columnName] {}然后根据需要在每个后代类中覆盖它,以对特定属性执行实际验证。

public class perObservableObject: ObservableObject, IDataErrorInfo
{
    private HashSet<string> InvalidProperties { get; } = new HashSet<string>();

    public virtual bool IsValid => !InvalidProperties.Any();

    public bool HasError(string propertyName) => InvalidProperties.Contains(propertyName);

    protected virtual string ValidateProperty(string propertyName) => string.Empty;

    public string this[string columnName]
    {
        get
        {
            if (nameof(IsValid).Equals(columnName))
                return string.Empty;

            var result = ValidateProperty(columnName);

            var errorStateChanged = string.IsNullOrWhiteSpace(result)
                ? InvalidProperties.Remove(columnName)
                : InvalidProperties.Add(columnName);

            if (errorStateChanged)
                RaisePropertyChanged(nameof(IsValid));

            return result;
        }
    }

    // IDataErrorInfo - redundant in WPF
    public string Error => string.Empty;
}

[ObservableObject 来自 MvvmLight]


推荐阅读