カスタムオブジェクトのコレクションにバインドされた非常に単純な 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 が内部のオブジェクトを検証し、オブジェクトが正しいかどうかをコードで検出できるようにしたいと考えています。私は次の方法を試しました:
UserControl にすべての検証エラーのコレクションを追加します
private readonly List<Tuple<object, ValidationError>> errors = new List<Tuple<object, ValidationError>>();
UserControl のコンストラクターに検証ハンドラーを追加します。
Validation.AddErrorHandler(this, ErrorChangedHandler);
ハンドルの検証が変更されました:
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 の検証エラーは、新しいオブジェクトの作成時に追加され、すべてに正しい値を入力した後でも削除されません。 2 つのフィールド。これが私のログです(すべての検証エラーを記録しました):
(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 に関連する最初の 2 つのエラーは削除されないため、すべてのエラーのリストは空ではなく、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>