2011-11-07 19 views
7

Tengo un DataGridComboBoxColum en un DataGrid. Me gustaría poder hacer clic en la celda una vez y tener desplegado el cuadro combinado. Actualmente tengo que hacer clic varias veces.DataGridComboBoxColumn - menú desplegable automático en un solo clic

<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

¿Necesita el 'DataGrid' para entrar en el modo de edición, es decir, el aumento de la BeginningEditEvent? – XAMeLi

+0

Nunca planteo el evento principiante. ¿Realmente necesito? –

+1

El primer clic en una celda es establecer el foco en la celda y (tal vez) seleccionarlo (depende del SelectionMode del 'DataGrid'), el segundo clic muestra el elemento EditingElement y es cuando se produce el BeginningEditEvent (por el' DataGrid '). Así que entiendo que no está manejando este evento, ni su lógica depende de si 'DataGrid' está en modo de edición (es decir, si IsEditingCurrentCell == true o IsEditingRowItem == true), ¿verdad? – XAMeLi

Respuesta

6

Un clic DataGridComboBoxColumn edición + un clic CheckboxColumn edición
Ver también: 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> 

de código subyacente:

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

El "Ver también" es cómo hacerlo. Use un DataGridTemplateColumn y establezca su CellTemplate en un ComboBox. – user1454265

2

que tenía problemas con @su Respuesta de rfen, probablemente porque es muchos años después y WPF probablemente ha cambiado bastante. Parece que DataGrid ahora se ocupa de algunas cosas, como editar un campo de texto automáticamente cuando comienza a escribir.

Utilizo un DataGridTemplateColumn para la columna de mi cuadro combinado. La plantilla tiene un TextBlock para su CellTemplate. La llamada al BeginEdit seguida de la llamada del operador hace que aparezca el cuadro combinado en el árbol visual. Luego, parece que el clic del mouse se envía al cuadro combinado y se abre solo.

Aquí está mi versión modificada del código de @ 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; 
    } 
} 
Cuestiones relacionadas