我有一个带有多个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");
}
}
}
如何通过为所有视图模型实现IDataErrorInfo或INotifyDataErrorInfo接口来完成验证?
我使用This文章,但在属性更改时验证并且不验证必填字段。
答案 0 :(得分:2)
这是一个使用IDataErrorInfo
的简单示例。这应该可以帮助您入门。
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>
代码背后:
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));
}
}
}
答案 1 :(得分:1)
您好,您必须创建一些方法来验证我的代码中的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
}
<强>&GT; XAML 强>
<TextBox Text="{Binding Password, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" Height="70" Width="200" />
xaml.cs
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
您需要从属性的setter调用Validate方法,该属性应用DataAnnotations并确保在通知PropertyChanged之前调用它。