我有一个 DataGrid,我绑定(bind)到“Customer”类的 ObservableCollection,实现 IDataErrorInfo。 Customer 类的属性之一是 int
,在我的 IDataErrorInfo 实现中,我检查它是否在有效范围内,例如:-
public class Customer : IDataErrorInfo
{
public int PercentDiscount { get; set; }
... other properties & methods removed for clarity
public string this[columnName]
{
get
{
if (PercentDiscount < 0 || PercentDiscount > 10)
return "Percent Discount is invalid";
}
}
}
在我的 XAML 代码隐藏中,我处理了几个事件。在 PreparingCellForEdit
事件中,我存储了对正在编辑的行的引用:-
private void DataGrid_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
_rowBeingEdited = e.Row;
}
然后在 RowEditEnding
事件中,如果该行处于无效状态,我会采取一些措施(在我的例子中,我将 Customer 属性恢复为之前的“良好”值):-
private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (_rowBeingEdited != null)
{
var errors = Validation.GetErrors(_rowBeingEdited);
if (errors.Count > 0)
{
.. do something
}
}
}
如果用户输入的数值未通过我的验证规则,这会正常工作,但如果用户输入非数值,则 RowEditEnding
事件永远不会触发并且单元格保持编辑状态.我假设这是因为 WPF 无法将非数字值绑定(bind)到 int
属性。发生这种情况时,有什么方法可以检测/处理吗?
最后的办法是将 PercentDiscount
属性更改为字符串,但我试图避免走这条路。
编辑 - 我刚刚发现我可以使用 CellEditEnding
事件而不是 RowEditEnding
成功处理这两种类型的错误。但是出现了一个新问题 - 如果我在单元格中输入无效值然后按 Enter,底层属性不会更新,因此当 CellEditEnding 触发 Validation.GetErrors
是空的。最终结果是该行离开了编辑模式,但仍然在带有红色边框的单元格中显示无效值。知道现在发生了什么吗?
最佳答案
这可能不是一个很好的答案,尤其是因为您已经提到了它,但我已经与 DataGrid 验证斗争了一段时间,最终求助于使我的支持值成为字符串。您会在调试器的输出窗口中注意到,当您将字母字符键入绑定(bind)到 int 的 DataGridColumn 时,会发生绑定(bind)或转换异常。
您可以通过更改 UpdateSourceTrigger 或在绑定(bind)和属性之间放置一个转换器来获得不同的行为,但在我用字符串支持这些值之前,我从来没有得到我需要的东西。
我想您也可以尝试创建自己的从 DataGridTextColumn 派生的 DataGridNumericColumn,也许您可以更好地控制绑定(bind)/验证行为。
关于WPF 数据网格验证不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15968106/