WPF DataGrid: Binding DataGridColumn visibility to ContextMenu MenuItems IsChecked (MVVM)

I just wrote a blog post on this topic. It allows DataGridColumns to be shown or hidden through a ContextMenu that is accessible by right-clicking any column header. This task is accomplished purely through attached properties so it is MVVM-compliant.

See blog post


I've been looking for a generic, XAML (i.e., no code-behind), automatic and simple example of a column chooser context menu that binds to a WPF DataGrid column header. I've read literally hundreds of articles, but none of them seem to do exactly the right thing, or they're no generic enough. So here's what I think is the best combined solution:

First, put these in the resource dictionary. I'll leave it as an exercise to the reader to write the Visibility/Boolean converter to ensure the checkboxes check when the column is visible and vice-versa. Note that by defining x:Shared="False" for the context menu resource, it'll get instance-specific state which means that you can use this single template/resource for all your datagrids and they'll all maintain their own state.

<Converters:VisiblityToInverseBooleanConverter x:Key="VisiblityToInverseBooleanConverter"/>

<ContextMenu x:Key="ColumnChooserMenu" x:Shared="False"
             DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" 
             ItemsSource="{Binding Columns, RelativeSource={RelativeSource AncestorType={x:Type sdk:DataGrid}}}">
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding Header}"/>
            <Setter Property="AutomationProperties.Name" Value="{Binding Header}"/>
            <Setter Property="IsCheckable" Value="True" />
            <Setter Property="IsChecked" Value="{Binding Visibility, Mode=TwoWay, Converter={StaticResource VisiblityToInverseBooleanConverter}}" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>

<Style x:Key="ColumnHeaderStyle" TargetType="{x:Type Primitives:DataGridColumnHeader}">
    <Setter Property="ContextMenu" Value="{StaticResource ColumnChooserMenu}" />
</Style>

<ContextMenu x:Key="GridItemsContextMenu" >
    <MenuItem Header="Launch Do Some other action"/>
</ContextMenu>

Then define the DataGrid as follows (where OrdersQuery is some data source exposed by the View-model):

<sdk:DataGrid ItemsSource="{Binding OrdersQuery}"
              AutoGenerateColumns="True" 
              ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
              ContextMenu="{StaticResource GridItemsContextMenu}">

  <!-- rest of datagrid stuff goes here -->

</sdk:DataGrid>

This will give you the following:

  1. A context menu bound to the column headings which acts as a column chooser.
  2. A context menu bound to the items in the grid (to perform actions on the items themselves - again, the binding of the actions is an exercise for the reader).

Hope this helps people who've been looking for an example like this.


I know this is a bit old. But I was looking at doing this and this post is much simpler: http://iimaginec.wordpress.com/2011/07/25/binding-wpf-toolkit%E2%80%99s-datagridcolumn-to-a-viewmodel-datacontext-propogation-for-datagrid-columns-the-mvvm-way-to-interact-with-datagridcolumn/

All you need to do is set DataContext on the Columns and then bind Visibility to your ViewModel as per normal! :) Simple and effective