2010-08-06 4 views
70

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

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

+0

Вы используете DataGrid, найденный в WPF Toolkit? –

+4

Не могли бы вы дать нам немного больше информации о том, что вы пробовали и как это не работает? –

ответ

7

От: 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; 
} 
+1

Это не работает в некоторых случаях, и это более сложное решение Micael Bergerons. – SwissCoder

+0

Для меня это было почти решением. Мне нужно было добавить обработчик событий «PreviewMouseLeftButtonUp» и поставить там точно такой же код. –

+0

это не работает, если у вас есть выпадающая скобка. клик предварительного просмотра видит щелчки на всплывающем окне combobox, затем вызов cell.focus вызывает все. Самое простое исправление - добавить раздел, который смотрит на исходный источник событий мыши, используя FindVisualParent, чтобы увидеть, находится ли он внутри datagrid. если нет, не делайте никакой другой работы. –

59

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

<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 (содержащий манекен Лицо объектов).

Магия случается там: 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); 
     } 
    } 

{наслаждаться}

+4

Вы можете обойти уже выбранную проблему с строкой, установив свойство 'SelectionUnit' в DataGrid на' Cell'. –

+2

Отличный материал! Но это не работает на флажках ... – Jan

+0

Предположим, у меня есть TextBox в моем DataGridCell. После того, как я назову 'grd.BeginEdit (e)', я хочу, чтобы TextBox в этой ячейке имел фокус. Как я могу это сделать? Я попытался вызвать 'FindName (« txtBox »)' как для DataGridCell, так и для DataGrid, но для меня он возвращает null. – user1214135

6

Решение от 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> 

Примечание х: атрибут 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's answer goes here. 
} 
32

Ответ от Micael Bergeron был хорошим началом для меня найти решение, которое работает для меня. Чтобы разрешить редактирование одним кликом также для ячеек в той же строке, что уже в режиме редактирования, мне пришлось немного ее отрегулировать. Использование CellUnit 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

checkboxes, похоже, не работает для меня? Мне все равно придется дважды щелкнуть их –

+0

Действительно, не работает для флажков –

1

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

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

Основная проблема, которую я нашел с ответом, заключается в том, что поведение клавиши ввода нарушено. 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, который не изменился никакого принципиального поведения реализации вне-коробки и все же поддерживает одним нажатием кнопки редактирования ,

-2
<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; 

} 
1

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

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

Не работает ... он теряет редактирование, как только мышь покидает ячейку. Таким образом, вы 1) щелкните левой кнопкой мыши на ячейке, которую хотите изменить. 2) переместите мышь в сторону. 3) Начните вводить текст. Ваш ввод не работает, потому что ячейка больше не находится в режиме редактирования. – Skarsnik

2

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

<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> 
+0

Это не работает, если в качестве шаблона редактирования используется combobox, я бы предположил, что другие, такие как флажок, который захватывает события мыши, – Steve

Смежные вопросы