2011-11-07 10 views
7

Ho un DataGridComboBoxColum in un DataGrid. Vorrei poter fare clic sulla cella una volta e avere la casella combinata a discesa. Attualmente devo fare clic più volte.DataGridComboBoxColumn - Auto a discesa con 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

Avete bisogno del 'DataGrid' per andare in modalità di modifica, vale a dire l'aumento del BeginningEditEvent? – XAMeLi

+0

Non ho mai alzato l'inizio. Ho bisogno di? –

+1

Il primo clic su una cella sta impostando lo stato attivo sulla cella e (forse) selezionandolo (dipende dal SelectionMode di 'DataGrid'), il secondo clic mostra l'EditingElement e il momento in cui viene generato BeginningEditEvent (dal' DataGrid '). Quindi capisco che non stai gestendo questo evento, né la tua logica dipende dal fatto che 'DataGrid' sia in modalità di modifica (vale a dire se IsEditingCurrentCell == true o IsEditingRowItem == true), giusto? – XAMeLi

risposta

6

One-click DataGridComboBoxColumn editing + uno scatto editing CheckboxColumn
Vedi anche: 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> 

Codice-behind:

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

Il "Vedere anche" è come farlo. Utilizzare un DataGridTemplateColumn e impostare il suo CellTemplate su un ComboBox. – user1454265

2

ho avuto problemi con @su la risposta di rfen, probabilmente perché sono passati molti anni e il WPF probabilmente è cambiato parecchio. Sembra che DataGrid ora si prenda cura di alcune cose per te, come la modifica di un campo di testo automaticamente quando inizi a digitare.

Io uso un DataGridTemplateColumn per la mia colonna casella combinata. Il modello ha un TextBlock per il suo CellTemplate. La chiamata a BeginEdit seguita dalla chiamata del dispatcher fa apparire la casella combinata nell'albero visivo. Sembra quindi che il clic del mouse venga inviato alla casella combinata e si apra da solo.

Ecco la mia versione modificata del @ di surfen codice:

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; 
    } 
} 
Problemi correlati