2 回答
TA贡献1895条经验 获得超7个赞
我意识到我不需要找到存在验证错误的单元格。我需要做的就是在所有单元格上调用 CancelEdit() 。
private void CancelChangesButton_Click(object sender, RoutedEventArgs e)
{
var cc = dataGrid.CurrentCell;
foreach (var col in datagrid.Columns)
{
datagrid.CurrentCell = new DataGridCellInfo(datagrid.CurrentItem, col);
datagrid.CancelEdit();
}
dataGrid.CurrentCell = cc;
}
它还可以与 DataGridTemplateColumn 一起使用。 解决方案代码
但是,如果您想查找哪些单元格包含验证错误,则需要更深入地研究。感谢@BionicCode,我找到了解决方案。
可以得到可视化的DataGridRow:
DataGridRow row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(item);
然后你就可以检查错误:
if (Validation.GetHasError(row))
并且您还可以访问row.BindingGroup,其中包含该行中的所有绑定 (.BindingExpressions) 以及许多其他信息(IsDirty、ValidationErrors、ValidationRules、CancelEdit())
但是,当您想要检查单元格中的错误时,事情就没那么容易了。不幸的是,DataGridCell 不包含有关错误的信息,Validation.GetHasError(cell)无法正常工作。您需要更深入地研究视觉树。
private void CancelChangesCellsHavingError()
{
SomethingItem item = datagrid.CurrentItem as SomethingItem;
DataGridRow row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromItem(item);
if (Validation.GetHasError(row))
{
var cc = dataGrid.CurrentCell;
foreach (DataGridColumn col in datagrid.Columns)
{
DataGridCell cell = (DataGridCell)col.GetCellContent(item).Parent;
List<DependencyObject> errs = GetVisualChildrenHavingError(cell);
if (errs != null)
{
datagrid.CurrentCell = new DataGridCellInfo(item, col);
datagrid.CancelEdit(DataGridEditingUnit.Cell);
}
}
dataGrid.CurrentCell = cc;
}
}
/// <summary>
/// Returns all visual children that HasError. Return null if nothing is found.
/// </summary>
public static List<DependencyObject> GetVisualChildrenHavingError(DependencyObject parent)
{
List<DependencyObject> result = null;
GetVisualChildrenHavingError(parent, ref result);
return result;
}
private static void GetVisualChildrenHavingError(DependencyObject parent, ref List<DependencyObject> result)
{
for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex++)
{
DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);
if (Validation.GetHasError(childElement))
{
if (result == null)
result = new List<DependencyObject>();
result.Add(childElement);
}
GetVisualChildrenHavingError(childElement, ref result);
}
}
有用的链接 - 绑定、验证、DataGrid:
TA贡献1864条经验 获得超2个赞
红细胞显示验证错误。只要存在验证错误,您就无法取消编辑模式(除非用户按Escape键)。
唯一的解决方案是通过简单地恢复输入来手动解决错误。
算法如下:
获取当前单元格
获取当前cell的容器
检查容器(单元)是否存在验证错误。如果是,则继续步骤 4,否则只需取消编辑(跳至步骤 9)
TextBox
获取单元格模板的编辑TextBox.Text
识别编辑属性的绑定源(数据项)属性获取属性的值(使用反射来实现通用行为)
恢复内容
将键盘焦点移回编辑
TextBox
,这将触发重新验证并定义取消的目标单元格。取消编辑
执行:
private void CancelChangesButton_Click(object sender, RoutedEventArgs e)
{
DependencyObject cellItemContainer = this.datagrid.ItemContainerGenerator.ContainerFromItem(
(this.datagrid.CurrentCell.Item as SomethingItem));
// If the current cell has validation errors find the edit TextBox child control
if (Validation.GetHasError(cellItemContainer) && TryFindChildElement(cellItemContainer, out TextBox editTextBox))
{
// Get the property name of he binding source
var propertyName = (editTextBox.BindingGroup.BindingExpressions.FirstOrDefault() as BindingExpression)?.ResolvedSourcePropertyName ?? string.Empty;
// Use reflection to get the value of the binding source
object value = this.datagrid.CurrentCell.Item.GetType().GetProperty(propertyName).GetValue(this.datagrid.CurrentCell.Item);
// Check which ToString() to invoke
editTextBox.Text = value is DateTime date
? date.ToShortDateString()
: value.ToString();
// Trigger validation and define which cell to cancel the edit
// This is required because the edit TexBox lost focus
Keyboard.Focus(editTextBox);
}
this.datagrid.CancelEdit();
}
// Traverses the visual tree to find a child element of type TElement
private bool TryFindVisualChild<TChild>(DependencyObject parent, out TChild resultElement) where TChild : DependencyObject
{
resultElement = null;
for (var childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex++)
{
DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);
if (childElement is Popup popup)
{
childElement = popup.Child;
}
if (childElement is TChild)
{
resultElement = childElement as TChild;
return true;
}
if (TryFindVisualChild(childElement, out resultElement))
{
return true;
}
}
return false;
}
- 2 回答
- 0 关注
- 224 浏览
添加回答
举报