Код, чтобы проверить, если ячейки DataGrid является в настоящее время отредактированы
Есть ли простая возможность проверить, находится ли в данный момент DataGrid в EditMode (без подписки на BeginningEdit и CellEditEnding)
4 ответа:
Похоже, вы также можете получить эту информацию из представления элементов, а именно это работает:
IEditableCollectionView itemsView = stateGrid.Items; if (itemsView.IsAddingNew || itemsView.IsEditingItem) { stateGrid.CommitEdit(DataGridEditingUnit.Row, true); }
Я не подтвердил это, но, скорее всего, вы могли бы получить эти флаги в viewmodel, если ваша связанная коллекция предоставляет IEditableCollectionView.
Хорошо, я не нашел простого решения, и никто не указал мне на него. Следующий код можно использовать для добавления вложенного свойства 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); } }
Чтобы использовать его, установите на datagrid свойство ProcessIsInEditMode в true:
<DataGrid local:DataGridIsInEditModeTracker.ProcessIsInEditMode="True" .. other properties ..>
После этого свойство IsInEditMode будет синхронизировано с режимом DataGrid. Если вы хотите также изменить ячейку редактирования, измените код в
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; }
Все ответы, приведенные выше с использованием IsEditing на datagridrow или IsEdititngItem на IEditableCollectionView, являются частичными ответами для меня:
Если пользователь вводит редакцию, то клики на любой другой ячейке, событие 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
Это в основном заставляет сетку устанавливать IsEditing = false на datagridrow, когда любая ячейка прекращает редактирование.