Binding Visibility for DataGridColumn in WPF
datagrid, visibility, wpf, xaml
Solution
First of all, `DataGridTextColumn` (or any other supported dataGrid column) does not lie in the Visual tree of the `DataGrid`. Hence, by default it doesn't inherit the `DataContext` of the `DataGrid`. However, it works for `Binding` DP only and for no other DP's on DataGridColumn.
Since they don't lie in the same VisualTree, any attempt to get the `DataContext` using `RelativeSource` won't work as well because `DataGridTextColumn` is unable to traverse up to the `DataGrid`.
There are two other ways to achieve this though:
First using a `Freezable` class. `Freezable` objects can inherit the DataContext even when they’re not in the visual or logical tree –We can take advantage of that.
First, create a class inheriting from `Freezable` and `Data` DP which we can use to bind in XAML:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy));
}
Now, add an instance of it in DataGrid resources so that it can inherit the DataGrid's DataContext and can bind with its Data DP:
<DataGrid>
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
Source={StaticResource proxy}}"/>
</DataGrid.Columns>
</DataGrid>
Second, you can refer to any UI element in XAML using `ElementName` or `x:Reference`. However, `ElementName` works only in the same visual tree, whereas x:Reference doesn't have such constraints.
So, we can use that as well to our advantage. Create a dummy `FrameworkElement` in XAML with Visibility set to `collapsed`. The FrameworkElement will inherit the DataContext from its parent container, which can be a Window or UserControl.
And can use that in DataGrid:
<FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Test"
Binding="{Binding Name}"
Visibility="{Binding DataContext.IsEnable,
Source={x:Reference dummyElement}}"/>
</DataGrid.Columns>
</DataGrid>
Problem
How can I hide a column in a WPF `DataGrid` through a Binding? This is what I did: ``` <DataGridTextColumn Header="Column header" Binding="{Binding ColumnValue}" Width="100" ElementStyle="{StaticResource DataGridRightAlign}" Visibility="{Binding MyColumnVisibility}" /> ``` And this is what I got (besides the column still visible): System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=MyColumnVisibility; DataItem=null; target element is 'DataGridTextColumn' (HashCode=1460142); target property is 'Visibility' (type 'Visibility') How to fix the binding?