使用INotifyDataErrorInfo在窗口加载时调用验证,WPF

时间:2017-10-27 10:17:40

标签: c# .net wpf validation data-binding

我有一个名为EditableSong的模型,它来自ValidatableModel类 实现INotifyPropertyChangedINotifyDataErrorInfo

class EditableSong : ValidatableModel
{
    CommandRelay addcommand = null;

    public ICommand AddCommand
    {
        get { return addcommand; }
    }

    public EditableSong()
    {
        addcommand = new CommandRelay(Add, CanAdd);
    }

    private void Add(object obj = null)
    {
        MessageBox.Show("Succesfully Added!");
    }

    private bool CanAdd(object obj = null)
    {
        return !HasErrors;
    }

    private string title;
    [Required]
    [MaxLength(45)]
    public string Title
    {
        get { return title; }
        set
        { SetProperty(ref title, value); }
    }

    private string lyrics;
    [MaxLength(3000)]
    public string Lyrics
    {
        get { return lyrics; }
        set { SetProperty(ref lyrics, value); }
    }

    private string artist;

    [Required]
    public string Artist
    {
        get { return artist; }
        set {SetProperty(ref artist, value); }
    }
}

这里是ValidatableModel课程:

class ValidatableModel : BindableBase, INotifyDataErrorInfo
{
    private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();

    public bool HasErrors
    {
        get  { return _errors.Count >0; ; }
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    protected override void SetProperty<T>(ref T member, T val,
         [CallerMemberName] string propertyName = null)
    {

        base.SetProperty(ref member, val, propertyName);
        ValidateProperty(propertyName, val);
    }

    public IEnumerable GetErrors(string propertyName)
    {
        if (_errors.ContainsKey(propertyName))
            return _errors[propertyName];
        else
            return null;
    }

    protected void ValidateProperty<T>(string propertyName, T value)
    {

        var results = new List<ValidationResult>();

        ValidationContext context = new ValidationContext(this);
        context.MemberName = propertyName;
        Validator.TryValidateProperty(value, context, results);

        if (results.Any())
        {
            _errors[propertyName] = results.Select(c => c.ErrorMessage).ToList();
        }
        else
        {
            _errors.Remove(propertyName);
        }

        ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
    }

    protected void OnErrorsChanged(string propName)
    {
        ErrorsChanged(this, new DataErrorsChangedEventArgs(propName));
    }
}`

它运行良好,但只有在我更改窗口的文本框中的属性之后。 主要问题是用户必须无法在不填写必填字段的情况下保存模型,但是当Windows加载按钮Save(使用命令)可用时,由于验证不运行。

这是xaml:

<Window x:Class="ValidationTests.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ValidationTests"
    xmlns:rules="clr-namespace:ValidationTests.Rules"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
    <Style x:Key="TextBoxError" TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate x:Name="TextErrorTemplate">
                    <DockPanel LastChildFill="True">
                        <AdornedElementPlaceholder>
                            <Border BorderBrush="Red" BorderThickness="2"/>
                        </AdornedElementPlaceholder>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<Grid>
    <StackPanel>
        <Label>Artist</Label>
        <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Artist,
            ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        </TextBox>
        <Label>Title</Label>
        <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Title,
            ValidatesOnNotifyDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        <Label>Lyrics</Label>
        <TextBox Style="{StaticResource TextBoxError}" Text="{Binding Lyrics,
            ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        <Button Content="Add" Command="{Binding AddCommand}"></Button>
    </StackPanel>
</Grid>

我想知道如何解决这个问题......

1 个答案:

答案 0 :(得分:1)

  

我想知道如何解决这个问题......

您需要预先执行实际验证。

ValidateProperty类的构造函数中的所有属性调用EditableSong方法,以填充Dictionary并举起ErrorsChanged事件:

public EditableSong()
{
    addcommand = new CommandRelay(Add, CanAdd);

    ValidateProperty(nameof(Title), title);
    ValidateProperty(nameof(Lyrics), lyrics);
    ValidateProperty(nameof(Artist), artist);
}