【发布时间】:2011-03-15 22:48:45
【问题描述】:
是否有一种简单的方法可以检查 DataGrid 当前是否处于 EditMode(无需订阅BeginningEdit 和 CellEditEnding)
【问题讨论】:
标签: wpf wpfdatagrid
是否有一种简单的方法可以检查 DataGrid 当前是否处于 EditMode(无需订阅BeginningEdit 和 CellEditEnding)
【问题讨论】:
标签: wpf wpfdatagrid
您似乎也可以从项目视图中获取此信息,即这有效:
IEditableCollectionView itemsView = stateGrid.Items;
if (itemsView.IsAddingNew || itemsView.IsEditingItem)
{
stateGrid.CommitEdit(DataGridEditingUnit.Row, true);
}
我尚未确认这一点,但如果您的绑定集合提供 IEditableCollectionView,您很可能可以在视图模型中获得这些标志。
【讨论】:
CollectionViewSource.GetDefaultView(stateGrid.Items)source获取itemsView更安全
好的,我还没有找到一个简单的解决方案,也没有人向我指出一个。以下代码可用于将附加属性 IsInEditMode 添加到 DataGrid。希望它可以帮助某人:
public class DataGridIsInEditModeTracker {
public static bool GetIsInEditMode(DataGrid dataGrid) {
return (bool)dataGrid.GetValue(IsInEditModeProperty);
}
private static void SetIsInEditMode(DataGrid dataGrid, bool value) {
dataGrid.SetValue(IsInEditModePropertyKey, value);
}
private static readonly DependencyPropertyKey IsInEditModePropertyKey = DependencyProperty.RegisterAttachedReadOnly("IsInEditMode", typeof(bool), typeof(DataGridIsInEditModeTracker), new UIPropertyMetadata(false));
public static readonly DependencyProperty IsInEditModeProperty = IsInEditModePropertyKey.DependencyProperty;
public static bool GetProcessIsInEditMode(DataGrid dataGrid) {
return (bool)dataGrid.GetValue(ProcessIsInEditModeProperty);
}
public static void SetProcessIsInEditMode(DataGrid dataGrid, bool value) {
dataGrid.SetValue(ProcessIsInEditModeProperty, value);
}
public static readonly DependencyProperty ProcessIsInEditModeProperty =
DependencyProperty.RegisterAttached("ProcessIsInEditMode", typeof(bool), typeof(DataGridIsInEditModeTracker), new FrameworkPropertyMetadata(false, delegate(DependencyObject d,DependencyPropertyChangedEventArgs e) {
DataGrid dataGrid = d as DataGrid;
if (null == dataGrid) {
throw new InvalidOperationException("ProcessIsInEditMode can only be used with instances of the DataGrid-class");
}
if ((bool)e.NewValue) {
dataGrid.BeginningEdit += new EventHandler<DataGridBeginningEditEventArgs>(dataGrid_BeginningEdit);
dataGrid.CellEditEnding += new EventHandler<DataGridCellEditEndingEventArgs>(dataGrid_CellEditEnding);
} else {
dataGrid.BeginningEdit -= new EventHandler<DataGridBeginningEditEventArgs>(dataGrid_BeginningEdit);
dataGrid.CellEditEnding -= new EventHandler<DataGridCellEditEndingEventArgs>(dataGrid_CellEditEnding);
}
}));
static void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) {
SetIsInEditMode((DataGrid)sender,false);
}
static void dataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e) {
SetIsInEditMode((DataGrid)sender, true);
}
}
要使用它,请将数据网格上的 ProcessIsInEditMode- 属性设置为 true:
<DataGrid local:DataGridIsInEditModeTracker.ProcessIsInEditMode="True" .. other properties ..>
您将拥有与 DataGrid 的模式同步的 IsInEditMode 属性。
如果您还想要编辑单元格,请相应更改BeginningEdit中的代码。
【讨论】:
我找到了一个更短的解决方法(VB.NET/C#):
VB.NET
<Extension>
Public Function GetContainerFromIndex(Of TContainer As DependencyObject) _
(ByVal itemsControl As ItemsControl, ByVal index As Integer) As TContainer
Return DirectCast(
itemsControl.ItemContainerGenerator.ContainerFromIndex(index), TContainer)
End Function
<Extension>
Public Function IsEditing(ByVal dataGrid As DataGrid) As Boolean
Return dataGrid.GetEditingRow IsNot Nothing
End Function
<Extension>
Public Function GetEditingRow(ByVal dataGrid As DataGrid) As DataGridRow
Dim sIndex = dataGrid.SelectedIndex
If sIndex >= 0 Then
Dim selected = dataGrid.GetContainerFromIndex(Of DataGridRow)(sIndex)
If selected.IsEditing Then Return selected
End If
For i = 0 To dataGrid.Items.Count - 1
If i = sIndex Then Continue For
Dim item = dataGrid.GetContainerFromIndex(Of DataGridRow)(i)
If item.IsEditing Then Return item
Next
Return Nothing
End Function
C#:
public static TContainer GetContainerFromIndex<TContainer>
(this ItemsControl itemsControl, int index)
where TContainer : DependencyObject
{
return (TContainer)
itemsControl.ItemContainerGenerator.ContainerFromIndex(index);
}
public static bool IsEditing(this DataGrid dataGrid)
{
return dataGrid.GetEditingRow() != null;
}
public static DataGridRow GetEditingRow(this DataGrid dataGrid)
{
var sIndex = dataGrid.SelectedIndex;
if (sIndex >= 0)
{
var selected = dataGrid.GetContainerFromIndex<DataGridRow>(sIndex);
if (selected.IsEditing) return selected;
}
for (int i = 0; i < dataGrid.Items.Count; i++)
{
if (i == sIndex) continue;
var item = dataGrid.GetContainerFromIndex<DataGridRow>(i);
if (item.IsEditing) return item;
}
return null;
}
【讨论】:
以上所有在 datagridrow 上使用 IsEditing 或在 IEditableCollectionView 上使用 IsEdititngItem 的答案都是对我的部分答案:
如果用户输入版本,然后单击任何其他单元格,则会触发 EndEdit 事件,但 DataGridRow 仍然将属性 IsEditing 设置为 True !!!如果你试图找到负责的 DataGridCell,它的 IsEditingProperty 总是假的...... 我认为这是一个错误。为了获得理想的行为,我必须编写这个丑陋的解决方法
Public Shared ReadOnly ForceEndEditProp As DependencyProperty =
DependencyProperty.RegisterAttached("ForceEndEdit", GetType(Boolean),
GetType(DataGridEditing), New PropertyMetadata(False, AddressOf ForceEndEditChanged))
Protected Shared Sub ForceEndEditChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim g As DataGrid = TryCast(d, DataGrid)
If g Is Nothing Then Return
''IsCommiting prevents a StackOverflow ...
Dim IsCommiting As Boolean = False
AddHandler g.CellEditEnding, Sub(s, e1)
If IsCommiting Then Return
IsCommiting = True
g.CommitEdit(DataGridEditingUnit.Row, True)
IsCommiting = False
End Sub
End Sub
Public Shared Function GetForceEndEdit(o As DependencyObject) As Boolean
Return o.GetValue(ForceEndEditProp)
End Function
Public Shared Sub SetForceEndEdit(ByVal o As DependencyObject, ByVal value As Boolean)
o.SetValue(ForceEndEditProp, value)
End Sub
当任何单元格停止编辑时,这基本上会强制网格在 datagridrow 上设置 IsEditing = false。
【讨论】: