1

我有一个非常简单的 DataGrid 绑定到自定义对象的集合。自定义对象使用 DataAnnotations 进行注释并实现 IDataErrorInfo。

public class MyObject : IDataErrorInfo {
    [Required(ErrorMessageResourceName = "Amount_Required", ErrorMessageResourceType = typeof(Resources))]
    [Range(typeof(decimal), "0", "1000000000", ErrorMessageResourceName = "InventoryCost_Amount_Invalid", ErrorMessageResourceType = typeof(Resources))]
    public decimal? Amount { get; set; }

    [Required(ErrorMessageResourceName = "Name_Required", ErrorMessageResourceType = typeof(Resources))]
    [StringLength(50, ErrorMessageResourceName = "Name_MaxLength", ErrorMessageResourceType = typeof(Resources))]
    public string Name { get; set; }

    // standard IDataErrorInfo stuff here
 }

我希望 DataGrid 验证其中的任何对象,并且我将能够在代码中检测对象是否正确。我尝试了以下方法:

  1. 在 UserControl 中添加所有验证错误的集合

    private readonly List<Tuple<object, ValidationError>> errors = new List<Tuple<object, ValidationError>>();
    
  2. 在 UserControl 的构造函数中添加验证处理程序:

    Validation.AddErrorHandler(this, ErrorChangedHandler);
    
  3. 处理验证更改:

    private void ErrorChangedHandler(object sender, ValidationErrorEventArgs e)
    {
        Debug.WriteLine(e.Action.ToString() + ":object=" + e.OriginalSource.ToString() + ",error=" + e.Error.ToString());
        if (e.Action == ValidationErrorEventAction.Added)
        {
            errors.Add(new Tuple<object, ValidationError>(e.OriginalSource, e.Error));
        }
        else
        {
            Tuple<object, ValidationError> error = errors.FirstOrDefault(err => err.Item1 == e.OriginalSource && err.Item2 == e.Error);
            if (error != null) { errors.Remove(error); }
        }
        bool hasError = !errors.Any();
    }
    

如果我编辑现有对象,这可以正常工作,但是如果我尝试添加新对象,错误更改的事件流非常奇怪:TextBlock 的验证错误在创建新对象时添加并且永远不会删除,即使我为所有对象设置了正确的值两个领域。这是我的日志(我记录了所有验证错误):

(I created new row,i.e. object)

添加:object=System.Windows.Controls.TextBlock,error=System.Windows.Controls.ValidationError 添加:object=System.Windows.Controls.TextBlock,error=System.Windows.Controls.ValidationError 添加:object=System.Windows。 Controls.TextBox,error=System.Windows.Controls.ValidationError 已添加:object=System.Windows.Controls.DataGridCell,error=System.Windows.Controls.ValidationError 已删除:object=System.Windows.Controls.DataGridCell,error=System。 Windows.Controls.ValidationError

(I put correct value for Name field)

已删除:object=System.Windows.Controls.TextBox,error=System.Windows.Controls.ValidationError 添加:object=System.Windows.Controls.TextBox,error=System.Windows.Controls.ValidationError 添加:object=System.Windows。 Controls.DataGridCell,error=System.Windows.Controls.ValidationError

(I put correct value for Amount field, now object (and whole row is the grid) is valid)

已删除:object=System.Windows.Controls.DataGridCell,error=System.Windows.Controls.ValidationError 已删除:object=System.Windows.Controls.TextBox,error=System.Windows.Controls.ValidationError

但是与 TextBlock 相关的前两个错误没有被删除,因此所有错误的列表不为空,并且 ErrorChangedHandler 中的 hasError 变量为 false。我的 XAML 也很简单:

    <DataGrid x:Name="grid"
              ItemsSource="{Binding MyObjects}" 
              CanUserDeleteRows="False" Margin="11,11,11,11" 
              AutoGenerateColumns="False"
              Height="308">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, 
                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" 
                                Header="Name" Width="100" ElementStyle="{StaticResource TextCellElementStyle}"
                                EditingElementStyle="{StaticResource TextCellEditingStyle}"/>
            <DataGridTextColumn Binding="{Binding Path=Amount, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, 
                                ValidatesOnExceptions=True, NotifyOnValidationError=True}" 
                                Header="Amount" Width="75" ElementStyle="{StaticResource TextCellElementStyle}"
                                EditingElementStyle="{StaticResource TextCellEditingStyle}"/>
        </DataGrid.Columns>
    </DataGrid>
4

0 回答 0