[WPF] Datagrid : Gérer la visibility d’une colonne avec un Binding

Le problème

J’ai rencontré récemment un besoin particulier durant la réalisation d’un écran WPF, le client souhaitait pouvoir afficher/masquer des colonnes selon plusieurs règles métiers.

Innocemment, je pensais qu’un simple Binding sur la propriété Visibility associé à un Boolean résoudrait mon affaire. MAIS QUE NENNI. Ceci n’est pas possible.


<DataGrid ItemsSource="{Binding Items}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Col 1" Binding="{Binding SomeProperty1}" Visibility="{Binding Col1IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}">                    
        </DataGridTextColumn>
        <DataGridTextColumn Header = "Col 2" Binding="{Binding SomeProperty2}" Visibility="{Binding Col2IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}">
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

Visual Studio nous sort une erreur :

 Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Col1IsVisible; DataItem=null; target element is ‘DataGridTextColumn’ (HashCode=1460142); target property is ‘Visibility’ (type ‘Visibility’)

En effet, les DataGridColumn n’héritent pas du DataContext de la DataGrid, et les DependencyProperty comme Visibility ne sont donc pas bindables.

La solution

Heureusement pour nous, il est possible de faire appel à une petite bidouille afin de rendre nos colonnes « pseudo-bindable ». Il faut en effet se reposer sur un élément XAML qui fera le proxy entre notre propriété et la colonne souhaitée.

<FrameworkElement x:Name="ProxyElement1" DataContext="{Binding}" Visibility="{Binding Col1IsVisible,Converter={StaticResource BooleanToVisibilityConverter}}" />
<FrameworkElement x:Name="ProxyElement2" DataContext="{Binding}" Visibility="{Binding Col2IsVisible,Converter={StaticResource BooleanToVisibilityConverter}}" />

<DataGrid ItemsSource="{Binding Items}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Col 1" Binding="{Binding SomeProperty1}" Visibility="{Binding Path=DataContext.Col1IsVisible, Source={x:Reference ProxyElement1},Converter={StaticResource BooleanToVisibilityConverter}}">
        </DataGridTextColumn>
        <DataGridTextColumn Header = "Col 2" Binding="{Binding SomeProperty2}" Visibility="{Binding Path=DataContext.Col2IsVisible, Source={x:Reference ProxyElement2},Converter={StaticResource BooleanToVisibilityConverter}}">
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

En ajoutant des « FrameworkElement » (ou tout autre objet XAML), et en bindant notre propriété, le Visual Tree XAML est maintenant capable d’appliquer la bonne visibility aux colonnes de la Datagrid.

%d blogueurs aiment cette page :