I have the following WPF sample program:
Xaml:
Solution proposed by H.B. is really good and has true WPF MVVM spirit. Use it where possible.
In my particular case something went wrong so I came out with different way, as my project is not strict MVVM, so I can use coded solution.
In CustomView.xaml name assigned to column:
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn x:Name="MachinesColumn" ... />
...
In CustomView.xaml.cs we have a simple property which directly changes visibility of column:
public Visibility MachinesColumnVisible
{
get { return MachinesColumn.Visibility; }
set
{
if (value == MachinesColumn.Visibility)
return;
MachinesColumn.Visibility = value;
}
}
Visibility on DataGridTextColumn is not a DependencyProperty and can't be databound. Use a DataGridTemplateColumn and bind the visibility of the controls within the template.
Edit: Actually, this statement only applies to silverlight. See this other SO question for further details.
How to bind DataGridColumn.Visibility?
I asked about the easiest way to tell whether a property is a dependency here.
How can I most easily determine whether a property is a dependency property?
A column in a datagrid is an abstract object which does not appear in the visual tree, thus you cannot use RelativeSource
-binding, ElementName
will not work either since it will not find a governing FrameworkContentElement so you are in kind of a bind.
One way that works is via Source
and x:Reference, for that you will need to name your window and move the column to its resources to avoid a cyclical dependency error:
<Window Name="_window" ...>
<Window.Resources>
<DataGridTextColumn x:Key="ThatPeskyColumn"
Binding="{Binding Size}"
Visibility="{Binding DataContext.Flag, Source={x:Reference _window}, Converter={StaticResource BoolToVis}}"/>
</Window.Resources>
<!-- ... -->
<DataGrid AutoGenerateColumns="False" Name="Blumen"
ItemsSource="{Binding Leaves}">
<DataGrid.Columns>
<StaticResource ResourceKey="ThatPeskyColumn"/>
<!-- ... -->
Great fun.
I would prefer a more elegant approach which involves using a Freezable
.
<Window.Resources>
<DiscreteObjectKeyFrame x:Key="FlagKey" Value="{Binding Flag}"/>
</Window.Resources>
<DataGridTextColumn ... Visibility="{Binding Value, Source={StaticResource FlagKey}, ...}" />