2011-11-07 10 views
7

Mam DataGridComboBoxColum w DataGrid. Chciałbym móc raz kliknąć komórkę i rozwinąć listę rozwijaną combobox. Obecnie muszę kliknąć kilka razy.DataGridComboBoxColumn - Automatyczne rozwijanie jednym kliknięciem

<DataGrid AutoGenerateColumns="False" Height="148" HorizontalAlignment="Left" Margin="48,85,0,0" Name ="dg_display" VerticalAlignment="Top" Width="645" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding}" SelectionChanged="DgDisplaySelectionChanged"> 
     <DataGrid.Columns> 
      <DataGridTextColumn IsReadOnly="True" Header="Symbol" Binding="{Binding Symbol}" /> 
      <DataGridTextColumn IsReadOnly="True" Header="Company ID" Binding="{Binding CompanyID}" /> 
      <DataGridComboBoxColumn IsReadOnly="False" Header="Sector" SelectedValueBinding="{Binding Sector}" DisplayMemberPath="{Binding [0]}" Visibility="Visible" > 
       <DataGridComboBoxColumn.EditingElementStyle> 
        <Style TargetType="ComboBox"> 
         <Setter Property="ItemsSource" Value="{Binding SectorList}" /> 
        </Style> 
       </DataGridComboBoxColumn.EditingElementStyle> 
       <DataGridComboBoxColumn.ElementStyle> 
        <Style TargetType="ComboBox"> 
         <Setter Property="ItemsSource" Value="{Binding SectorList}" /> 
        </Style> 
       </DataGridComboBoxColumn.ElementStyle> 
      </DataGridComboBoxColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
+0

Czy potrzebujesz 'DataGrid', aby przejść do trybu edycji, czyli podniesienie BeginningEditEvent? – XAMeLi

+0

Nigdy nie wychowuję początkuedytetu. Czy muszę? –

+1

Pierwsze kliknięcie na komórce ustawia fokus na komórkę i (być może) wybiera ją (zależy od SelectionMode 'DataGrid'), drugie kliknięcie pokazuje EditingElement i to jest kiedy podniesiony został BeginningEditEvent (przez' DataGrid '). Rozumiem, że nie obsługujesz tego zdarzenia, a twoja logika zależy od tego, czy 'DataGrid' jest w trybie edycji (tj. Czy IsEditingCurrentCell == true czy IsEditingRowItem == true), prawda? – XAMeLi

Odpowiedz

6

Jedno kliknięcie DataGridComboBoxColumn edycji + jeden click edycji CheckboxColumn
Zobacz także: https://stackoverflow.com/a/8333704/724944

XAML:

 <Style TargetType="{x:Type DataGridCell}"> 
      <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" /> 
      <EventSetter Event="PreviewTextInput" Handler="DataGridCell_PreviewTextInput" /> 
     </Style> 

Code-tył:

private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     DataGridCell cell = sender as DataGridCell; 
     GridColumnFastEdit(cell, e); 
    } 

    private void DataGridCell_PreviewTextInput(object sender, TextCompositionEventArgs e) 
    { 
     DataGridCell cell = sender as DataGridCell; 
     GridColumnFastEdit(cell, e); 
    } 

    private static void GridColumnFastEdit(DataGridCell cell, RoutedEventArgs e) 
    { 
     if (cell == null || cell.IsEditing || cell.IsReadOnly) 
      return; 

     DataGrid dataGrid = FindVisualParent<DataGrid>(cell); 
     if (dataGrid == null) 
      return; 

     if (!cell.IsFocused) 
     { 
      cell.Focus(); 
     } 

     if (cell.Content is CheckBox) 
     { 
      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; 
       } 
      } 
     } 
     else 
     { 
      ComboBox cb = cell.Content as ComboBox; 
      if (cb != null) 
      { 
       //DataGrid dataGrid = FindVisualParent<DataGrid>(cell); 
       dataGrid.BeginEdit(e); 
       cell.Dispatcher.Invoke(
       DispatcherPriority.Background, 
       new Action(delegate { })); 
       cb.IsDropDownOpen = true; 
      } 
     } 
    } 


    private 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; 
    } 
+0

"Zobacz też" to jak to zrobić. Użyj DataGridTemplateColumn i ustaw jego CellTemplate na ComboBox. – user1454265

2

miałem problemy z @su Odpowiedź Rfena, prawdopodobnie dlatego, że minęło wiele lat i prawdopodobnie WPF uległa pewnej zmianie. Wydaje się, że teraz DataGrid zajmuje się niektórymi sprawami, takimi jak edycja pola tekstowego automatycznie po rozpoczęciu pisania.

Używam DataGridTemplateColumn dla mojej kolumny pola kombi. Szablon ma TextBlock dla swojego CellTemplate. Wywołanie BeginEdit, po którym następuje wywołanie dyspozytora powoduje, że pole kombi pojawia się w drzewie wizualnym. Następnie wydaje się, że kliknięcie myszą jest wysyłane do pola kombi i otwiera się samo.

Oto moja zmodyfikowana wersja kodu użytkownika @ surfen:

public static class DataGridExtensions 
{ 
    public static void FastEdit(this DataGrid dataGrid) 
    { 
     dataGrid.ThrowIfNull(nameof(dataGrid)); 

     dataGrid.PreviewMouseLeftButtonDown += (sender, args) => { FastEdit(args.OriginalSource, args); }; 
    } 

    private static void FastEdit(object source, RoutedEventArgs args) 
    { 
     var dataGridCell = (source as UIElement)?.FindVisualParent<DataGridCell>(); 

     if (dataGridCell == null || dataGridCell.IsEditing || dataGridCell.IsReadOnly) 
     { 
      return; 
     } 

     var dataGrid = dataGridCell.FindVisualParent<DataGrid>(); 

     if (dataGrid == null) 
     { 
      return; 
     } 

     if (!dataGridCell.IsFocused) 
     { 
      dataGridCell.Focus(); 
     } 

     if (dataGridCell.Content is CheckBox) 
     { 
      if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow) 
      { 
       if (!dataGridCell.IsSelected) 
       { 
        dataGridCell.IsSelected = true; 
       } 
      } 
      else 
      { 
       var dataGridRow = dataGridCell.FindVisualParent<DataGridRow>(); 

       if (dataGridRow != null && !dataGridRow.IsSelected) 
       { 
        dataGridRow.IsSelected = true; 
       } 
      } 
     } 
     else 
     { 
      dataGrid.BeginEdit(args); 

      dataGridCell.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => { })); 
     } 
    } 
} 

public static class UIElementExtensions 
{ 
    public static T FindVisualParent<T>(this UIElement element) 
     where T : UIElement 
    { 
     UIElement currentElement = element; 

     while (currentElement != null) 
     { 
      var correctlyTyped = currentElement as T; 

      if (correctlyTyped != null) 
      { 
       return correctlyTyped; 
      } 

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

     return null; 
    } 
} 
Powiązane problemy