2015-01-27 9 views
8

Ho un DataGrid in WPF con un DataGridTextColum e DataGridTemplateColum.Montaggio automatico dei contenuti datagrid WPF quando datagrid celle si concentrerà

<DataGridTextColumn Width="4*" IsReadOnly="True" x:Name="dataGridColumnDescription" 
Header="Description" Binding="{Binding Description}"> 
</DataGridTextColumn> 

<DataGridTemplateColumn CellStyle="{StaticResource CellEditing}" IsReadOnly="False" Width="*" Header="Value" 
CellEditingTemplateSelector="{StaticResource myCellEditingTemplateSelectorValue}" 
CellTemplateSelector="{StaticResource myCellTemplateSelectorValue}"> 
</DataGridTemplateColumn> 

Le CellTemplateSelectors restituiscono un DataTemplate con un TextBlock per il resp il CellTemplate. un TextBox per CellEditing!

<DataTemplate x:Key="dGridStringValueTemplate"> 
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Path=Value}"/> 
</DataTemplate> 

<DataTemplate x:Key="dGridStringValueTemplateEditing"> 
    <TextBox TextAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" BorderThickness="1" Text="{Binding Path=Value, UpdateSourceTrigger=LostFocus}"/> 
</DataTemplate> 

Ora voglio concentrarmi automaticamente il TextBox quando la DataGridCell ottiene la messa a fuoco. L'utente dovrebbe essere in grado di modificare il contenuto del TextBox senza fare doppio clic sulla cella.

Ho trovato questo articolo:

DataGrid Tips & Tricks: Single-Click Editing dove posso trovare il DataGridCell corrente, ma come posso accedere al contenuto della casella di testo per dare il focus per modificare il contenuto?

Questo è il mio stile:

<Style x:Key="CellEditing" TargetType="{x:Type DataGridCell}"> 
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="myDataGridMain_PreviewMouseLeftButtonDown"></EventSetter> 
</Style> 

Questo è il mio gestore di eventi:

private void myDataGridMain_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    DataGridCell cell = sender as DataGridCell;  // cell ist not null 

    DataGridTemplateColumn col = cell.Column as DataGridTemplateColumn; //col is not null 

    DataTemplate template = col.CellTemplate; //this is null 
} 

Come posso ottenere la casella di testo con quel gestore di eventi?

+0

Quando si desidera la griglia di essere modificabile tutto il tempo perché vuoi modificare il modello? aggiungi semplicemente il modello di cella con la casella di testo e cambia lo stile della casella di testo stessa in questo modo non devi scrivere elementi di messa a fuoco – WPFKK

risposta

2

l'ho fatta, non è la migliore soluzione, ma funziona ... Quando cellulare arriva a fuoco ho impostato in modalità di modifica.

private void myDataGridMain_OnFocus(object sender, RoutedEventArgs e) 
{ 
    DataGridCell cell = sender as DataGridCell; 
    if (cell != null) 
     cell.IsEditing = true; 
    //var test = FindVisualChild<TextBlock>(cell); 
} 

Su Keydown, cerco l'elemento visivo e il focus.

private void myDataGridMain_KeyDown(object sender, KeyEventArgs e) 
     { 
      DataGridCell cell = sender as DataGridCell; 

      if (e.Key == Key.Enter) 
      { //give cell the focus 
       cell.Focus(); 
      } 
      else 
      { 
       if ((cell != null)) 
       { 
        TextBox textbox = FindVisualChild<TextBox>(cell); 
        if (textbox != null) 
        { //TextBox has benn found 
         if ((textbox as TextBox).IsFocused == false) 
         { 
          (textbox as TextBox).SelectAll(); 
         } 
         (textbox as TextBox).Focus(); 
        } 

        CheckBox chkbox = FindVisualChild<CheckBox>(cell); 
        if (chkbox != null) 
        { //Checkbox has been found 
         (chkbox as CheckBox).Focus(); 
        } 

        ComboBox combbox = FindVisualChild<ComboBox>(cell); 
        if (combbox != null) 
        { //ComboBox has been found 
         (combbox as ComboBox).Focus(); 
        } 
       } 
      } 
     } 

Trova Visual Child!

public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(obj, i); 
     if (child != null && child is T) 
      return (T)child; 
     else 
     { 
      T childOfChild = FindVisualChild<T>(child); 
      if (childOfChild != null) 
       return childOfChild; 
     } 
    } 
    return null; 
} 
11

Questo sembra funzionare:

<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn> 
       <DataGridTemplateColumn.CellEditingTemplate> 
        <DataTemplate> 
         <TextBox FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"></TextBox> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellEditingTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
+0

Grazie per la risposta.In combinazione con un selettore di modelli questo non funziona :( – nullxff

+1

Grazie, sei un grande mago! – Yola

0

Questo approccio funziona per me. Esso utilizza il fatto che il DataGrid sarà sempre creare una nuova istanza del modello quando la redazione inizia:

<DataGridTemplateColumn.CellEditingTemplate> 
    <DataTemplate> 
     <TextBox Text="{Binding MyProperty}" 
       Loaded="TextBox_Loaded"></TextBox> 
    </DataTemplate> 
</DataGridTemplateColumn.CellEditingTemplate> 

e nel codice dietro:

private void TextBox_Loaded(object sender, RoutedEventArgs e) 
{ 
    ((TextBox)sender).Focus(); 
    ((TextBox)sender).SelectAll(); 
} 

Come bonus aggiuntivo, si seleziona anche tutto testo nella cella. Dovrebbe funzionare non importa come si entra in modalità di modifica (doppio click, click, premendo F2)

0

la risposta semplice per questo creare un nuovo controllo derivato dal controllo DataGrid

using System.Windows.Controls; 

    public class CustomDataGrid : DataGrid 
    { 

    protected override void OnSelectedCellsChanged(SelectedCellsChangedEventArgs e) 
    { 
     //to make sure cell is selected 
     var cells = e.AddedCells.FirstOrDefault(); 
     if (cells != null) 
     { 
      this.BeginEdit(); 

     } 
     base.OnSelectedCellsChanged(e); 
    } 

    }