web-dev-qa-db-fra.com

Edition automatique du contenu de la grille de données WPF lorsque la cellule de la grille de données est activée

J'ai un datagrid dans WPF avec un DataGridTextColum et un DataGridTemplateColum .

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

CellTemplateSelectors renvoie un DataTemplate avec un TextBlock pour le resp. Celltemplate. une TextBox pour 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>

Maintenant, je veux mettre au point automatiquement la zone de texte lorsque le DataGridCell obtient le focus. L'utilisateur doit pouvoir modifier le contenu de la zone de texte sans double-cliquer sur la cellule.

J'ai trouvé cet article:

Trucs et astuces dans DataGrid: Édition en un seul clic Où je peux obtenir le DataGridCell actuel, mais comment puis-je accéder au contenu pour donner à la zone de texte le focus pour l'éditer?

C'est mon style:

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

Ceci est mon gestionnaire d'événement:

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
}

Comment puis-je obtenir la zone de texte avec ce gestionnaire d'événements?

10
nullxff

Je l’ai réussi, ce n’est pas la meilleure solution mais ça marche ... Quand Cell a le focus, je le mets en mode édition.

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

Sur Keydown, je recherche l'enfant visuel et lui donne le 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();
                    }
                }
            }
        }

Trouver un enfant visuel!

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

Cela semble fonctionner:

    <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>
15
eran otzap

Cette approche fonctionne pour moi. Il utilise le fait que la DataGrid créera toujours une nouvelle instance du modèle lorsque la modification commencera:

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

et dans le code derrière:

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

En prime, il sélectionne également tout le texte de la cellule. Cela devrait fonctionner quelle que soit la manière dont vous entrez en mode d'édition (double clic, clic simple, appui sur F2)

0
vesan

la réponse simple pour créer un nouveau contrôle dérivé du contrôle 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);
    }

   }
0
Hisham