WPF : Retrouver l’index d’une cellule

WPF est un framework MVVM, pour ceux ayant fait du Angular, c’est la même approche. Il y a la View, le Model et le ViewModel.

Le ViewModel et en quelquesorte l’objet qui contient les données et est lié à la vue (View), vient tout de suite la notion de binding (unidirectionnel ou bidirectionnel. Le binding est la lisaison qui assur la synchronisation des valeurs entre le ViewModel et la vue.

Contenu

Binding bidirectionnel

Toute modification d’une valeur d’un champs texte aura une répercussion sur la même valeur dans le ViewModel. Et toute modification de valeur dans le ViewModel (via du code bien sûr puisque l’utilisateur n’a pas accès au ViewModel) aura une répercussion dans la vue.

Dans AngularJS, on a souvent parlé de cette notion de binding bidirectionnel car c’est ce qui a fait vendre ce framework.

Le problème posé en WPF avec la Datagrid

Le Datagrid est un peu comme une feuille de calcul Excel, c’est un ensemble de lignes et de colonnes. On a souvent besoin de déclencher une action (d’édition par exemple) quand on clique ou double clique sur une cellule, éditer l’entité qui contient cette cellule et mettre à jour dans la base de données cette entité.

La difficulté (ou non) est de retrouver l’id de cette rangée quand on a capturé l’entité. Sur le Net, j’ai vu des tuto alambiqués, qui font peur par leur complexité. En fait c’est plus simple que ça en a l’air. Ceci à condition d’avoir bien balisé  le noeud XAML avec un identifiant unique. Cet identifiant unique, on va le faire intelligemment c’est l’id dans la table de la base de données.

Supposons que vous ayez bindé une List<Url> à Datagrid.ItemsSource, tous vos Url sont mappés aux rangées de la Datagrid. Et chaque propriété de Url est dans une cellule de la rangée.

Utiliser la classe Helper VisualTreeHelper

Cette classe a plusieurs méthodes qui vous aident à traverser le visual tree de votre application WPF, on peut faire le parallèle avec une page HTML. Donc ça peut être très compliqué. Nos allons utiliser la méthode GetParent, qui va retourner le parent de la cellule.

Exemple de pistage de la cellule cliquée

Soit le code XAML suivant :

<TabItem Header="Visualisation des Urls">
    <DataGrid x:Name="ListeUrls" AutoGenerateColumns="False" Margin="1,0,-1,27" >
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}">
                <EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Id}" Visibility="Hidden"></DataGridTextColumn>
            <DataGridTextColumn Header="Vendor" Binding="{Binding Vendor}" Foreground="red" FontWeight="Bold" ></DataGridTextColumn>
            <DataGridTextColumn Header="Url" Binding="{Binding url}" ></DataGridTextColumn>
            
        </DataGrid.Columns>
    </DataGrid>
</TabItem>

On y met un DataGridTextColumn qui contient l’Id, qu’on a bindé, et on le met caché.

Un double Click sur la rangée va nous retourner un objet DataGridCell

private void DataGridCell_MouseDoubleClick(object sender, MouseButtonEventArgs e)
       {
           var dataGridCellTarget = (DataGridCell)sender;
           var parent = VisualTreeHelper.GetParent(dataGridCellTarget);
           .....
       }

La DataGridCell ne contient que la valeur de la cellule (plus d’autres paramètres), en mode débuggage lorsque vous inspectez la valeur de parent, vous verrez les 3 propriétés (Id,Vendor,url), dans la propriété DataContext de parent. Bingo ! Ce DataContext contient le nom de la classe Url.

 

Retour en haut