繁体   English   中英

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

[英]Call validation on when window loads, WPF using INotifyDataErrorInfo

我有一个名为EditableSong模型,它派生自实现INotifyPropertyChangedINotifyDataErrorInfo ValidatableModel类。

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 加载按钮保存(使用命令)可用时,因为验证没有运行。

这是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>

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM