[英]Call validation on when window loads, WPF using INotifyDataErrorInfo
I have model named EditableSong
which is derived from ValidatableModel
Class which implements INotifyPropertyChanged
and INotifyDataErrorInfo
.我有一个名为
EditableSong
模型,它派生自实现INotifyPropertyChanged
和INotifyDataErrorInfo
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); }
}
}
And here is ValidatableModel
class:这是
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));
}
}`
And it works well, but only after I change properties in textboxes of my window.它运行良好,但只有在我更改窗口文本框中的属性之后。 The main problem is that user mustn't be able to save model without filling required fields, but when windows loads button Save (which uses command) available, because of validation doesn't run.
主要问题是用户不能在不填写必填字段的情况下保存模型,但是当 Windows 加载按钮保存(使用命令)可用时,因为验证没有运行。
Here is xaml:这是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>
I wonder how can i fix this...我想知道我该如何解决这个问题...
I wonder how can i fix this...
我想知道我该如何解决这个问题...
You need to perform the actual validation upfront.您需要预先执行实际的验证。
Call the ValidateProperty
method for all properties in the constructor of your EditableSong
class to populate the Dictionary
and raise the ErrorsChanged
event:在
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.