wpf mvvm 中的数据验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18041514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Data Validation in mvvm
提问by ar.gorgin
I have a application with multiply ViewModels. Some property have DataAnnotations.
我有一个具有多个 ViewModel 的应用程序。某些属性具有 DataAnnotations。
[Required(ErrorMessage = "Field 'Range' is required.")]
[Range(1, 10, ErrorMessage = "Field 'Range' is out of range.")]
public int Password
{
get
{
return _password;
}
set
{
if (_password != value)
{
_password = value;
RaisePropertyChanged("Password");
}
}
}
How validation can be done by implementing the IDataErrorInfo or INotifyDataErrorInfo interface for all viewmodels?
如何通过为所有视图模型实现 IDataErrorInfo 或 INotifyDataErrorInfo 接口来完成验证?
I use Thisarticle, but validate when propertychange and don't validate required field.
我使用这篇文章,但在属性更改时验证并且不验证必填字段。
回答by Anand Murali
Here is a simple example which uses IDataErrorInfo. This should help you get started.
这是一个简单的例子,它使用IDataErrorInfo. 这应该可以帮助您入门。
XAML:
XAML:
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="LeftErrorTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding AdornedElement.(Validation.Errors).[0].ErrorContent, ElementName=ErrorAdorner}" Background="Red" Foreground="White" FontWeight="Bold" VerticalAlignment="Center"/>
<AdornedElementPlaceholder x:Name="ErrorAdorner">
<Border BorderBrush="Red" BorderThickness="1" />
</AdornedElementPlaceholder>
</StackPanel>
</ControlTemplate>
</Grid.Resources>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="158,66,0,0" Name="textBlock1" Text="Name" VerticalAlignment="Top" Width="44" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="217,65,0,0" Name="textBox1" VerticalAlignment="Top" Width="120"
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Validation.ErrorTemplate="{StaticResource LeftErrorTemplate}"/>
</Grid>
Code behind:
后面的代码:
using System;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
this.DataContext = vm;
}
}
public class ViewModel : ObservableBase, IDataErrorInfo
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
string errorMessage = string.Empty;
switch (columnName)
{
case "Name":
if (string.IsNullOrEmpty(Name))
errorMessage = "Enter name";
else if (Name.Trim() == string.Empty)
errorMessage = "Enter valid name";
break;
}
return errorMessage;
}
}
}
public class ObservableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
回答by yo chauhan
Hi you will have to create some method that Validates the annotations Like ValidateMethod in my code
嗨,您将必须创建一些方法来验证我的代码中的注释,例如 ValidateMethod
public class ViewModel:INotifyPropertyChanged,IDataErrorInfo
{
int _password;
[Required(ErrorMessage = "Field 'Range' is required.")]
[Range(1, 10, ErrorMessage = "Field 'Range' is out of range.")]
public int Password
{
get
{
return _password;
}
set
{
if (_password != value)
{
_password = value;
Validate("Password", value);
Notify("Password");
}
}
}
private void Validate(string propertyName, object value)
{
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");
string error = string.Empty;
var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(2);
bool result = Validator.TryValidateProperty(
value,
new ValidationContext(this, null, null)
{
MemberName = propertyName
},
results);
if (!result && (value == null || ((value is int || value is long) && (int)value == 0) || (value is decimal && (decimal)value == 0)))
return;
if (!result)
{
System.ComponentModel.DataAnnotations.ValidationResult validationResult = results.First();
if (!errorMessages.ContainsKey(propertyName))
errorMessages.Add(propertyName, validationResult.ErrorMessage);
}
else if (errorMessages.ContainsKey(propertyName))
errorMessages.Remove(propertyName);
}
#region INotifyPropertyChanged
public void Notify(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region IDataErrorInfo
public string Error
{
get { throw new NotImplementedException(); }
}
private Dictionary<string, string> errorMessages = new Dictionary<string, string>();
public string this[string columnName]
{
get
{
if(errorMessages.ContainsKey(columnName))
return errorMessages[columnName];
return null;
}
}
#endregion
}
>xaml
> xml
<TextBox Text="{Binding Password, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" Height="70" Width="200" />
xaml.cs
xml文件
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
You need to call the Validate method from setter of the property which applies DataAnnotations and make sure call it before Notifying the PropertyChanged.
您需要从应用 DataAnnotations 的属性的 setter 调用 Validate 方法,并确保在通知 PropertyChanged 之前调用它。

