C# 如何使用INotifyDataErrorInfo接口验证可观察集合
我正在使用C# 如何使用INotifyDataErrorInfo接口验证可观察集合,c#,wpf,validation,mvvm,inotifydataerrorinfo,C#,Wpf,Validation,Mvvm,Inotifydataerrorinfo,我正在使用MVVM模式和Prism框架开发WPF应用程序 我有一个基本的数据类,如下所示 public class ProductDecorator : DecoratorBase<Product> { private string _ProductShortName; private Boolean _IsSelected = false; // I have omitted some code for clarity here. [Requir
MVVM
模式和Prism
框架开发WPF
应用程序
我有一个基本的数据类,如下所示
public class ProductDecorator : DecoratorBase<Product>
{
private string _ProductShortName;
private Boolean _IsSelected = false;
// I have omitted some code for clarity here.
[Required]
public int ProductID
{
get { return BusinessEntity.ProductID; }
set
{
SetProperty(() => BusinessEntity.ProductID == value,
() => BusinessEntity.ProductID = value);
}
}
public Boolean IsSelected
{
get { return _IsSelected; }
set
{
SetProperty(ref _IsSelected, value);
}
}
}
公共类ProductDecorator:DecoratorBase
{
私有字符串_ProductShortName;
私有布尔值_isselect=false;
//为了清楚起见,我省略了一些代码。
[必需]
公共int ProductID
{
获取{return BusinessEntity.ProductID;}
设置
{
SetProperty(()=>BusinessEntity.ProductID==值,
()=>BusinessEntity.ProductID=value);
}
}
公营部门选举产生
{
获取{return}IsSelected;}
设置
{
SetProperty(参考值为选定值);
}
}
}
我在ViewModel中创建上述数据类的可观察集合
public class SaleInvoiceViewModel {
private ObservableCollection<ProductDecorator> _productDecorators;
public ObservableCollection<ProductDecorator> ProductDecorators
{
get { return _productDecorators; }
set { SetProperty(ref _productDecorators, value); }
}
}
公共类SaleInvoiceViewModel{
私人可观察收集(productDecorators);;
公共可观察收集产品装饰器
{
获取{return\u productDecorators;}
集合{SetProperty(ref _productDecorators,value);}
}
}
我将这个可观察的集合绑定到视图中的列表框
<telerik:RadListBox ItemsSource="{Binding ProductDecorators}" HorizontalAlignment="Stretch" Margin="5,10,5,5" Grid.Column="1" VerticalAlignment="Top">
<telerik:RadListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Margin="2" IsChecked="{Binding IsSelected}" />
<TextBlock Text="{Binding ProductShortName}" FontSize="14" />
</StackPanel>
</DataTemplate>
</telerik:RadListBox.ItemTemplate>
</telerik:RadListBox>
从上面的上下文中,我想验证“用户必须在列表框中选择至少一项”。换句话说,IsSelected
属性必须是可观察集合中的ProductUmDecorators
类中的true
目前我使用
INotifyDataErrorInfo
接口和数据注释
作为验证规则。我已经失去了我应该如何实现我的问题以实现此验证 有关stackoverflow的问题很多,但没有确切的答案。所以我决定发布我的解决方案作为这个问题的答案。
问题的背景是勾选“用户必须在列表框中选择一个与可观察集合绑定的项目”
第一步,ObservableCollection
needIsSelected
属性中的项(实体)
public class ProductDecorator : DecoratorBase<Product>
{
private string _ProductShortName;
private Boolean _IsSelected = false;
// I have omitted some code for clarity here.
public Boolean IsSelected
{
get { return _IsSelected; }
set
{
SetProperty(ref _IsSelected, value);
}
}
}
仔细查看上述代码中的EntityPropertyChanged
方法。只要ObservableCollection
中的任何项中的任何属性发生更改,就会触发此方法。然后,您只需在EntityPropertyChanged
方法中调用Validate
方法
private void EntityPropertyChanged( object sender, PropertyChangedEventArgs e )
{
if (e.PropertyName == "IsSelected")
this.Product.ValidateProperty("ProductUmDecorators");
}
如果更改的属性是IsSelected
,则将运行ValidatedProperty
方法。
我将省略ValidateProperty
方法的详细实现。此方法将尝试使用DataAnnotations
验证属性,并在出现任何错误时触发ErrorChanged事件。你可以了解细节
最后,您需要在Entity/ViewModel/Decorator类中实现自定义的DataAnnotation
ValidationAttribute
,在该类中,ObservableCollection
属性作为以下代码存在
public class SaleInvoiceViewModel {
private ObservableCollection<ProductDecorator> _productDecorators;
[AtLeastChooseOneItem(ErrorMessage = "Choose at least one item in the following list.")]
public ObservableCollection<ProductDecorator> ProductDecorators
{
get { return _productDecorators; }
set { SetProperty(ref _productDecorators, value); }
}
}
public class AtLeastChooseOneItem : ValidationAttribute
{
protected override ValidationResult IsValid( object value, ValidationContext validationContext )
{
ProductDecorator tmpEntity = (ProductDecorator) validationContext.ObjectInstance;
var tmpCollection = (ObservableCollection<ProductUmDecorator>) value;
if ( tmpCollection.Count == 0 )
return ValidationResult.Success;
foreach ( var item in tmpCollection )
{
if ( item.IsSelected == true )
return ValidationResult.Success;
}
return new ValidationResult( ErrorMessage );
}
}
公共类SaleInvoiceViewModel{
私人可观察收集(productDecorators);;
[AtLeastChooseOneItem(ErrorMessage=“在以下列表中至少选择一项。”)]
公共可观察收集产品装饰器
{
获取{return\u productDecorators;}
集合{SetProperty(ref _productDecorators,value);}
}
}
公共类至少选择一项:ValidationAttribute
{
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext)
{
ProductDecorator tmpEntity=(ProductDecorator)validationContext.ObjectInstance;
var tmpCollection=(ObservableCollection)值;
if(tmpCollection.Count==0)
返回ValidationResult.Success;
foreach(tmpCollection中的var项)
{
如果(item.IsSelected==true)
返回ValidationResult.Success;
}
返回新的ValidationResult(ErrorMessage);
}
}
这是一个有点复杂的解决方案,但这是迄今为止我发现的最可靠的解决方案。我会选择一个SelectedProductUmDecorator聚会,如果为空,则将其标记为无效。您必须有其他方法来指示集合中的选定元素[edit:duh,yeah],因此如果未选择任何元素,可以尝试将ProductUmDecorators标记为无效?
public class SaleInvoiceViewModel {
private ObservableCollection<ProductDecorator> _productDecorators;
[AtLeastChooseOneItem(ErrorMessage = "Choose at least one item in the following list.")]
public ObservableCollection<ProductDecorator> ProductDecorators
{
get { return _productDecorators; }
set { SetProperty(ref _productDecorators, value); }
}
}
public class AtLeastChooseOneItem : ValidationAttribute
{
protected override ValidationResult IsValid( object value, ValidationContext validationContext )
{
ProductDecorator tmpEntity = (ProductDecorator) validationContext.ObjectInstance;
var tmpCollection = (ObservableCollection<ProductUmDecorator>) value;
if ( tmpCollection.Count == 0 )
return ValidationResult.Success;
foreach ( var item in tmpCollection )
{
if ( item.IsSelected == true )
return ValidationResult.Success;
}
return new ValidationResult( ErrorMessage );
}
}