Редактирование одного клика в WPF DataGrid

Я хочу, чтобы пользователь мог поместить ячейку в режим редактирования и выделить строку, в которую содержится ячейка, одним щелчком. По умолчанию это двойной щелчок. Как переопределить или реализовать это? Я искал в google, и ответ codeplex не работает для меня.

Я новичок в WPF и кодировании в целом, поэтому простой ответ лучше.

Ответ 1

Вот как я решил эту проблему:

<DataGrid DataGridCell.Selected="DataGrid_GotFocus" ItemsSource="{Binding Source={StaticResource itemView}}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Nom" Binding="{Binding Path=Name}"/>
        <DataGridTextColumn Header="Age" Binding="{Binding Path=Age}"/>
    </DataGrid.Columns>
</DataGrid>

Этот DataGrid привязан к объекту CollectionViewSource (содержащему фиктивные Person).

Магия случается там: DataGridCell.Selected = "DataGrid_GotFocus" .

Я просто подключаю выбранное событие ячейки DataGrid и вызываю BeginEdit() в DataGrid.

Вот код для обработчика событий:

    private void DataGrid_GotFocus(object sender, RoutedEventArgs e)
    {
        // Lookup for the source to be DataGridCell
        if (e.OriginalSource.GetType() == typeof(DataGridCell))
        {
            // Starts the Edit on the row;
            DataGrid grd = (DataGrid)sender;
            grd.BeginEdit(e);
        }
    }

{} пользоваться

Ответ 2

Ответ от Micael Bergeron был хорошим началом для меня найти решение, которое работает для меня. Чтобы разрешить редактирование одним кликом также для ячеек в той же строке, что уже в режиме редактирования, мне пришлось немного ее отрегулировать. Использование SelectionUnit Cell не было для меня вариантом.

Вместо использования события DataGridCell.Selected, которое запускается только при первом щелчке ячейки ячейки, я использовал событие DataGridCell.GotFocus.

<DataGrid DataGridCell.GotFocus="DataGrid_CellGotFocus" />

Если вы это сделаете, у вас всегда будет правильная сотовая фокусировка и в режиме редактирования, но управление в ячейке не будет сфокусировано, это я решил как это

private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e)
{
    // Lookup for the source to be DataGridCell
    if (e.OriginalSource.GetType() == typeof(DataGridCell))
    {
        // Starts the Edit on the row;
        DataGrid grd = (DataGrid)sender;
        grd.BeginEdit(e);

        Control control = GetFirstChildByType<Control>(e.OriginalSource as DataGridCell);
        if (control != null)
        {
            control.Focus();
        }
    }
}

private T GetFirstChildByType<T>(DependencyObject prop) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(prop); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild((prop), i) as DependencyObject;
        if (child == null)
            continue;

        T castedProp = child as T;
        if (castedProp != null)
            return castedProp;

        castedProp = GetFirstChildByType<T>(child);

        if (castedProp != null)
            return castedProp;
    }
    return null;
}

Ответ 3

От: http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing

XAML:

<!-- SINGLE CLICK EDITING -->
<Style TargetType="{x:Type dg:DataGridCell}">
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
</Style>

КОД-ЗА:

//
// SINGLE CLICK EDITING
//
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
    {
        if (!cell.IsFocused)
        {
            cell.Focus();
        }
        DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
        if (dataGrid != null)
        {
            if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
            {
                if (!cell.IsSelected)
                    cell.IsSelected = true;
            }
            else
            {
                DataGridRow row = FindVisualParent<DataGridRow>(cell);
                if (row != null && !row.IsSelected)
                {
                    row.IsSelected = true;
                }
            }
        }
    }
}

static T FindVisualParent<T>(UIElement element) where T : UIElement
{
    UIElement parent = element;
    while (parent != null)
    {
        T correctlyTyped = parent as T;
        if (correctlyTyped != null)
        {
            return correctlyTyped;
        }

        parent = VisualTreeHelper.GetParent(parent) as UIElement;
    }

    return null;
}

Ответ 4

Решение от http://wpf.codeplex.com/wikipage?title=Single-Click%20Editing отлично поработало для меня, но я включил его для каждого DataGrid, используя стиль, определенный в ResourceDictionary. Чтобы использовать обработчики в ресурсных словарях, вам нужно добавить к нему файл с кодом. Вот как вы это делаете:

Это словарь ресурсов DataGridStyles.xaml:

<ResourceDictionary x:Class="YourNamespace.DataGridStyles"
            x:ClassModifier="public"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="DataGrid">
        <!-- Your DataGrid style definition goes here -->

        <!-- Cell style -->
        <Setter Property="CellStyle">
            <Setter.Value>
                <Style TargetType="DataGridCell">                    
                    <!-- Your DataGrid Cell style definition goes here -->
                    <!-- Single Click Editing -->
                    <EventSetter Event="PreviewMouseLeftButtonDown"
                             Handler="DataGridCell_PreviewMouseLeftButtonDown" />
                </Style>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Обратите внимание на атрибут x: Class в корневом элементе. Создайте файл класса. В этом примере это будет DataGridStyles.xaml.cs. Поместите этот код внутри:

using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;

namespace YourNamespace
{
    partial class DataGridStyles : ResourceDictionary
    {

        public DataGridStyles()
        {
          InitializeComponent();
        }

     // The code from the myermian answer goes here.
}

Ответ 5

Я предпочитаю этот путь на основе предложения Дюшана Кнежевича. вы щелкните по нему))

<DataGrid.Resources>

    <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
        <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver"
                                   Value="True" />
                        <Condition Property="IsReadOnly"
                                   Value="False" />
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="IsEditing"
                                Value="True" />
                    </MultiTrigger.Setters>
                </MultiTrigger>
        </Style.Triggers>
    </Style>

</DataGrid.Resources>

Ответ 6

Есть две проблемы с ответом user2134678. Один из них очень незначительный и не имеет функционального эффекта. Другой довольно значителен.

Первая проблема заключается в том, что GotFocus фактически вызывается против DataGrid, а не DataGridCell на практике. Спецификатор DataGridCell в XAML является избыточным.

Основная проблема, которую я нашел с ответом, заключается в том, что поведение ключа Enter нарушено. Enter должен переместить вас в следующую ячейку ниже текущей ячейки в обычном поведении DataGrid. Однако, что на самом деле происходит за кулисами, событие GotFocus будет вызываться дважды. Однажды на текущей ячейке, теряющей фокус, и однажды на новую ячейку, получающую фокус. Но до тех пор, пока BeginEdit вызывается в этой первой ячейке, следующая ячейка никогда не будет активирована. Результат заключается в том, что вы редактируете один клик, но любой, кто буквально не щелкает по сетке, будет неудовлетворен, а разработчик пользовательского интерфейса не должен предполагать, что все пользователи используют мыши. (Пользователи клавиатуры могут обойти это, используя Tab, но это все равно означает, что они прыгают через обручи, которые им не нужны.)

Итак, решение этой проблемы? Обработать событие KeyDown для ячейки, и если клавиша - клавиша Enter, установите флаг, который останавливает BeginEdit от включения в первую ячейку. Теперь клавиша Enter ведет себя так, как должна.

Для начала добавьте в свой DataGrid следующий стиль:

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridCell}" x:Key="SingleClickEditingCellStyle">
        <EventSetter Event="KeyDown" Handler="DataGridCell_KeyDown" />
    </Style>
</DataGrid.Resources>

Примените этот стиль к свойству "CellStyle" столбцам, для которых вы хотите включить один клик.

Затем в коде позади у вас есть следующее в вашем обработчике GotFocus (обратите внимание, что я использую VB здесь, потому что это то, что наш клиент запросов на клики с одним щелчком мыши хотел в качестве языка разработки):

Private _endEditing As Boolean = False

Private Sub DataGrid_GotFocus(ByVal sender As Object, ByVal e As RoutedEventArgs)
    If Me._endEditing Then
        Me._endEditing = False
        Return
    End If

    Dim cell = TryCast(e.OriginalSource, DataGridCell)

    If cell Is Nothing Then
        Return
    End If

    If cell.IsReadOnly Then
        Return
    End If

    DirectCast(sender, DataGrid).BeginEdit(e)
    .
    .
    .

Затем вы добавляете обработчик для события KeyDown:

Private Sub DataGridCell_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.Key = Key.Enter Then
        Me._endEditing = True
    End If
End Sub

Теперь у вас есть DataGrid, который не изменил никакого фундаментального поведения из готовой реализации и все же поддерживает редактирование одним щелчком.

Ответ 7

Я решил это, добавив триггер, который устанавливает свойство IsEditing для DataGridCell в True, когда мышь над ним. Это решило большинство моих проблем. Он также работает с comboboxes.

<Style TargetType="DataGridCell">
     <Style.Triggers>
         <Trigger Property="IsMouseOver" Value="True">
             <Setter Property="IsEditing" Value="True" />
         </Trigger>
     </Style.Triggers>
 </Style>

Ответ 8

 <DataGridComboBoxColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Setter Property="cal:Message.Attach" 
                            Value="[Event MouseLeftButtonUp] = [Action ReachThisMethod($source)]"/>
                        </Style>
                    </DataGridComboBoxColumn.CellStyle>
 public void ReachThisMethod(object sender)
 {
     ((System.Windows.Controls.DataGridCell)(sender)).IsEditing = true;

 }