我有一个DataGrid,我绑定到一个ObservableCollection的“Customer”类,实现了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
事件中,如果行处于无效状态,我会采取一些措施(在我的情况下,我将客户属性恢复为之前的“好”值): -
private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (_rowBeingEdited != null)
{
var errors = Validation.GetErrors(_rowBeingEdited);
if (errors.Count > 0)
{
.. do something
}
}
}
如果用户输入的数值不符合我的验证规则,则此方法正常,但如果用户输入非数字值,则RowEditEnding
事件永远不会触发,并且单元格仍处于编辑状态。我认为这是因为WPF无法将非数字值绑定到int
属性。有什么办法可以在发生这种情况时检测/处理吗?
最后的办法是将PercentDiscount
属性更改为字符串,但我正试图避免沿着这条路走下去。
修改 - 我刚刚发现我可以使用CellEditEnding
事件代替RowEditEnding
成功处理这两种类型的错误。但是出现了一个新问题 - 如果我在单元格中输入了无效值,则按 Enter ,基础属性不会更新,因此当CellEditEnding触发Validation.GetErrors
为空时。最终结果是该行离开编辑模式但仍显示具有红色边框的单元格中的无效值。知道现在发生了什么吗?
答案 0 :(得分:1)
这可能不是一个很好的答案,特别是因为你已经提到它,但我已经与DataGrid验证了一段时间,并最终诉诸于使我的支持值成为字符串。您将在调试器的输出窗口中注意到,当您在绑定到int的DataGridColumn中键入alpha字符时,会发生绑定或转换异常。
你可以通过更改UpdateSourceTrigger或在转换器和属性之间放置一个转换器来获得不同的行为,但是在用字符串支持值之前,我从来没有得到我需要的内容。
我想您也可以尝试创建从DataGridTextColumn派生的自己的DataGridNumericColumn,也许您可以更好地控制绑定/验证行为。
答案 1 :(得分:1)
我很难为此找到一个好的解决方案,但是我看到其他一些人搞乱了CellEditEnding事件而且我最终得到了这些代码,如果转换失败则会恢复值:
private void CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditingElement is TextBox)
{
var cellTextBox = (TextBox)e.EditingElement;
var cellTextBoxBinding = cellTextBox.GetBindingExpression(TextBox.TextProperty);
if (cellTextBoxBinding != null && !cellTextBoxBinding.ValidateWithoutUpdate())
{
cellTextBoxBinding.UpdateTarget();
}
}
}
如果值的转换失败,则在编辑元素绑定上调用ValidateWithoutUpdate会返回false,然后调用UpdateTarget强制将值恢复为当前的模型&#39;值。