Wpf 使用IDataError进行验证

Wpf 使用IDataError进行验证,wpf,validation,datagrid,mvvm,idataerrorinfo,Wpf,Validation,Datagrid,Mvvm,Idataerrorinfo,我的viewmodel中有以下验证方法(示例仅显示一列“ItemNumber”): public bool有效 { 得到 { foreach(ValidatedProperties中的字符串属性) 如果(GetValidationError(属性)!=null) 返回false; 返回true; } } 静态只读字符串[]ValidatedProperties= { “项目编号” }; 字符串GetValidationError(字符串属性名称) { if(Array.IndexOf(Vali

我的viewmodel中有以下验证方法(示例仅显示一列“ItemNumber”):

public bool有效
{
得到
{
foreach(ValidatedProperties中的字符串属性)
如果(GetValidationError(属性)!=null)
返回false;
返回true;
}
}
静态只读字符串[]ValidatedProperties=
{ 
“项目编号”
};
字符串GetValidationError(字符串属性名称)
{
if(Array.IndexOf(ValidatedProperties,propertyName)<0)
返回null;
字符串错误=null;
交换机(propertyName)
{
案例“项目编号”:
error=this.ValidateItemNumber();
打破
违约:
Debug.Fail(“ProjectExpense上验证的意外属性:+propertyName”);
打破
}
//将UI上的状态消息设置为生成的错误
if(错误!=null)
{
ErrorMessage=错误;
}
返回误差;
}
//字符串方法
静态布尔IsStringMissing(字符串值)
{
返回String.IsNullOrEmpty(value)| | value.Trim()==String.Empty;
}
字符串ValidateItemNumber()
{
如果(SelectedProjectExpenseItem!=null)
{
如果(IsString正在丢失(SelectedProjectExpenseItem.ItemNumber))
{
返回“需要项目编号”;
}
如果(SelectedProjectExpenseItem.ItemNumber.Length>50)
{
返回“项目编号超过50个字符”;
}
}
返回null;
}
#端区
#区域IDataErrorInfo成员
字符串IDataErrorInfo.Error{get{return null;}}
字符串IDataErrorInfo。此[string propertyName]
{
获取{返回this.GetValidationError(propertyName);}
}
验证将启动,但我不知道如何将其与我的datagrid通信。我使用了一个单独的Dto(因此上面选择了SelectedProjectExpenseItem.ItemNumber,SelectedProjectExpenseItem是我的Dto),而不是直接在我的viewmodel中使用属性。这是我的数据网格:

  <DataGrid ItemsSource="{Binding Path=ListOfProjectExpenseItems}" AutoGenerateColumns="False" 
      Name="dgProjectExpenseItems" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True" 
      SelectedItem="{Binding Path=SelectedProjectExpenseItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" GridLinesVisibility="Horizontal" CanUserDeleteRows="True" CanUserAddRows="True">
    <DataGrid.Columns>
      <DataGridTextColumn Header="ID" Width="SizeToCells" MinWidth="50" Binding="{Binding RowID}" />
      <DataGridTextColumn Header="Project Expense ID" Width="SizeToCells" Visibility="Hidden" MinWidth="0" Binding="{Binding ProjectExpenseID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Item Number" Width="SizeToCells" MinWidth="140" Binding="{Binding ItemNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Item Description" Width="SizeToCells" MinWidth="250" Binding="{Binding ItemDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Unit Price" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Qty" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Supplier Name" Width="SizeToCells" MinWidth="200" Binding="{Binding SupplierName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </DataGrid.Columns>
  </DataGrid>

我想使用一种样式,比如带有红色边框和说明错误的工具提示,来表示行或单元格有问题。但是,我发现的每个使用样式的示例都直接在viewmodel中具有这些属性,我不知道如何将其移植到Dto


非常感谢您的帮助。

您的绑定上是否有
validatesOnDaerRors=True、validatesOnceptions=True、NotifyOnValidationError=True
处于活动状态

这些问题与我在实现中使用Dto有关,或者至少与它们中缺少实现IDataErrorInfo有关。我决定放弃它们,直接使用实现IDataErrorInfo和wa la的业务对象,现在一切都运行得很好。

在这种情况下,我总是用带有IDataErrorInfo实现的ViewModel包装DTO。但听起来你只想继续使用DTO…我并不反对将DTO中的属性放在viewmodel中,但我必须重写代码才能这样做。也许这是更好的选择…现在我测试了它,IDataError甚至没有在我的datagrid列上启动。我有一个bool IsValid属性绑定到一个调用验证的save按钮。我可能不得不重新思考这个问题。我想我要重新发布我的问题,因为我发现了一些让我抓狂的事情。好吧,我把它放在那里了,但我想我的问题是IDataErrorInfo甚至没有开火。一旦我发现这一点,我就开始写另一篇文章。我认为这与我的dg绑定到ObservableCollection有关,并且没有将字段单独指定为vm中的属性。
  <DataGrid ItemsSource="{Binding Path=ListOfProjectExpenseItems}" AutoGenerateColumns="False" 
      Name="dgProjectExpenseItems" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True" 
      SelectedItem="{Binding Path=SelectedProjectExpenseItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" GridLinesVisibility="Horizontal" CanUserDeleteRows="True" CanUserAddRows="True">
    <DataGrid.Columns>
      <DataGridTextColumn Header="ID" Width="SizeToCells" MinWidth="50" Binding="{Binding RowID}" />
      <DataGridTextColumn Header="Project Expense ID" Width="SizeToCells" Visibility="Hidden" MinWidth="0" Binding="{Binding ProjectExpenseID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Item Number" Width="SizeToCells" MinWidth="140" Binding="{Binding ItemNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Item Description" Width="SizeToCells" MinWidth="250" Binding="{Binding ItemDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Unit Price" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Qty" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
      <DataGridTextColumn Header="Supplier Name" Width="SizeToCells" MinWidth="200" Binding="{Binding SupplierName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </DataGrid.Columns>
  </DataGrid>