Код, чтобы проверить, если ячейки DataGrid является в настоящее время отредактированы


Есть ли простая возможность проверить, находится ли в данный момент DataGrid в EditMode (без подписки на BeginningEdit и CellEditEnding)

4 8

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, когда любая ячейка прекращает редактирование.