I want to control DataGrid
column visibility through a ContextMenu
available to the user by right-clicking the column header. The ContextMenu
displays the names of all available columns. I am using MVVM design pattern.
My question is: How do I bind the DataGridColumn
's Visibility
property to the IsChecked
property of a MenuItem
located in the ContextMenu
.
Some mockup code:
<UserControl.Resources>
<ContextMenu x:Key="ColumnHeaderContextMenu">
<MenuItem Header="Menu Item..1" IsCheckable="True" />
</ContextMenu>
<Style x:Key="ColumnHeaderStyle"
TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Setter Property="ContextMenu"
Value="{StaticResource ColumnHeaderContextMenu}" />
</Style>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</UserControl.Resources>
...flaf flaf flaf
<toolkit:DataGrid x:Name="MyGrid" AutoGenerateColumns="False"
ItemsSource="{Binding MyCollection, Mode=Default}"
EnableColumnVirtualization="True" IsReadOnly="True"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">
<toolkit:DataGrid.Columns>
<toolkit:DataGridTextColumn Binding="{Binding Path=MyEntry}"
Header="MyEntry" Visibility="{Binding IsChecked, Converter=
{StaticResource booleanToVisibilityConverter}.... />
</toolkit:DataGrid.Columns>
</toolkit:DataGrid>
If I am being unclear please let me know and I will attempt to elaborate.
Cheers,
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 datagrid's and they'll all maintain their own state.
Then define the DataGrid as follows (where OrdersQuery is some data source exposed by the View-model):
This will give you the following:
Hope this helps people who've been looking for an example like this.
Instead of booleanToVisibilityConverter you can use x:static
Statics in XAML: http://msdn.microsoft.com/en-us/library/ms742135.aspx
I did try to ge this to bind to the ContextMenu using 'ElementName', but in the end, got it work using Properties in the VM, e.g.
and in the XAML:
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
Ok, this has been quite the exercise for a WPF n00b.
IanR thanks for the suggestion I used a similar aproach but it dosent take you all the way.
Here is what I have come up with if anyone can find a more consistent way of doing it I will appreciate any comments:
Impediments:
DataGridColumnHeader does not support a context menu. Therefore the context menu needs to be applied as a Style.
The contextmenu has its own datacontext so we have to use findancestor to link it to the ViewModels datacontext.
ATM the DataGrid control does not parse its datacontext to its Columns. This could be solved in codebehind however we are using the MVVM pattern so I decided to follow jamiers approach
Solution:
Place the following two blocks of code in Window.Resources
The datagrid then looks something like this in XAML
So the visibility property on the DataGridColumn and the ischeked property are both databound to the IsHidden property on the viewModel.
In the ViewModel:
The Helper class defined by Jaimer:
Instanciated in the viewmodel (just to show done through Unity in real project)
Cheers,
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