I am trying to control the visibility of a column using a checkbox (this is in WPF 4.0).
Here is a snippet of my XAML:
<Window.Resources> <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> </Window.Resources> <CheckBox x:Name="GeneralDetailsVisible" Content="General Details" Margin="5"/> <DataGridTextColumn Header="Crew" Binding="{Binding Path=Crew}" Visibility="{Binding ElementName=GeneralDetailsVisible, Converter={StaticResource BoolToVisConverter}, Path=IsChecked}"> </DataGridTextColumn>
Now I know that the BooleanToVisibilityConverter converter works when I bind it to a text block, and I see the values ββthat I expect. If I manually enter the values ββin the column visibility property, it will work. But not when I associate this. What am I doing wrong?
Answer:
The quartermaster pointed me to the answer. The page he pointed to is a bit misleading, because the code provided in the message does not work, and you should look at the code example.
Here is my last working code for anyone facing this problem:
to turn our viewModels bool property into the correct visibility value for our column attribute.
<Window.Resources> <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> </Window.Resources>
Bind the checkmark to the ViewModels property, which will control the visibility of the columns.
<CheckBox x:Name="DetailsVisible" Content="Show Details" IsChecked="{Binding Path=DisplayDetails}" />
Then bind the visibility to the ViewModels DisplayDetails property. Note that this is a column that is bound to a DataContext.
<DataGridTextColumn Header="Reliability" Binding="{Binding Path=Reliability}" Visibility="{Binding (FrameworkElement.DataContext).DisplayDetails, RelativeSource={x:Static RelativeSource.Self}, Converter={StaticResource BoolToVisConverter}}"> </DataGridTextColumn>
Add the following code to your project, this will catch the change in the DataCrtext DataGrids.
FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn)); FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid), new FrameworkPropertyMetadata (null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged)));
Then, whenever the DataContext DataGrids changes, we update all connected DataGridColumsn with the new DataContext.
public static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DataGrid grid = d as DataGrid; if (grid != null) { foreach (DataGridColumn col in grid.Columns) { col.SetValue(FrameworkElement.DataContextProperty, e.NewValue); } } }
One Gotcha to look for. If you add your DataContext to your page as follows:
<Window.DataContext> <vm:WeaponListViewModel /> </Window.DataContext>
Then the above function will be called before your DataGrid has any columns!
I got around this by manually binding my DataConext to the code after creating the window.