在WPF DataGrid中的TextBlock上未调用Validation.ErrorChangedHandler

时间:2012-05-03 19:35:17

标签: .net wpf validation datagrid

我有一个非常简单的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();
    }
    
  4. 如果我编辑现有对象,这是正确的,但如果我尝试添加新对象,则错误更改事件流非常奇怪:TextBlock的验证错误会添加到即使我为所有两个字段添加了正确的值,也会创建并永远不会删除新对象。这是我的日志(我记录了所有验证错误):

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

    添加了:对象= System.Windows.Controls.TextBlock,误差= System.Windows.Controls.ValidationError     添加了:对象= System.Windows.Controls.TextBlock,误差= System.Windows.Controls.ValidationError     添加了:对象= System.Windows.Controls.TextBox,误差= System.Windows.Controls.ValidationError     添加了:对象= System.Windows.Controls.DataGridCell,误​​差= System.Windows.Controls.ValidationError     删除:对象= System.Windows.Controls.DataGridCell,误​​差= System.Windows.Controls.ValidationError

    (I put correct value for Name field)
    

    移除:对象= System.Windows.Controls.TextBox,误差= System.Windows.Controls.ValidationError     添加了:对象= System.Windows.Controls.TextBox,误差= System.Windows.Controls.ValidationError     添加了:对象= System.Windows.Controls.DataGridCell,误​​差= System.Windows.Controls.ValidationError

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

    移除:对象= System.Windows.Controls.DataGridCell,误​​差= System.Windows.Controls.ValidationError     删除:对象= System.Windows.Controls.TextBox,误差= 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>
    

0 个答案:

没有答案