How to hide datagrid wpf columns depending on property

I have the following sample WPF program:

Xaml:

<Window x:Class="AncestorArie.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <BooleanToVisibilityConverter x:Key="BoolToVis" /> </Window.Resources> <Grid> <DataGrid AutoGenerateColumns="False" Name="Blumen" ItemsSource="{Binding Leaves}"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Color}" Header="Farbe" Width="160" /> <DataGridTextColumn Binding="{Binding Size}" Header="Größe" Width="60" Visibility="{Binding Path=DataContext.Flag, RelativeSource={RelativeSource Findancestor, AncestorType={x:Type Window}}, Converter={StaticResource BoolToVis}}" /> </DataGrid.Columns> </DataGrid> </Grid> </Window> 

Code behind:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Flowers rose = new Flowers(); rose.Leaves = new ObservableCollection<Leaf>(); rose.Flag = false; Leaf L1 = new Leaf(); L1.Color = "rot"; L1.Size = 3; rose.Leaves.Add(L1); Leaf L2 = new Leaf(); L2.Color = "gelb"; L2.Size = 2; rose.Leaves.Add(L2); this.DataContext = rose; } } 

And model classes:

 public class Leaf { public string Color { get; set; } public int Size { get; set; } } public class Flowers { public bool Flag { get; set; } public ObservableCollection<Leaf> Leaves { get; set; } } 

As you can see, I want to hide the second column of the datagrid if the Flag property is set to false. But that will not work. I get the following binding error in the Visual Studio output window:

Error System.Windows.Data: 4: Cannot find source for binding with link 'RelativeSource FindAncestor, AncestorType =' System.Windows.Window ', AncestorLevel =' 1 ''. BindingExpression: Path = DataContext.Flag; DataItem = NULL; target element "DataGridTextColumn" (HashCode = 44856655); target property "Visibility" (type "Visibility")

What is wrong with my code regarding the Visibility attribute?

+17
c # data-binding wpf xaml datagrid
Jul 28 '11 at 10:52
source share
4 answers

The column in the datagrid is an abstract object that does not appear in the visual tree, so you cannot use the RelativeSource -binding, ElementName will not work because it will not find the FrameworkContentElement control, so you are in the binding view.

One way to work is through Source and x:Reference , for this you will need to name your window and move the column to its resources in order to avoid a cyclic 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 pleasure.

+42
Jul 28 '11 at 12:24
source share

Visibility in a DataGridTextColumn is not a DependencyProperty and cannot be bound to a database. Use a DataGridTemplateColumn and bind the visibility of the controls in the template.

Edit: Actually, this statement applies only to silverlight. See this other SO question for more information.

How to bind DataGridColumn.Visibility?

I asked about the easiest way to find out if a property is dependent here.

How can I most easily determine if a property is a dependency property?

+4
Jul 28 2018-11-11T00:
source share

I would prefer a more elegant approach that involves using Freezable .

 <Window.Resources> <DiscreteObjectKeyFrame x:Key="FlagKey" Value="{Binding Flag}"/> </Window.Resources> <DataGridTextColumn ... Visibility="{Binding Value, Source={StaticResource FlagKey}, ...}" /> 
+3
Nov 07 '16 at 5:39
source share

The solution proposed by HB is really good and has the true spirit of WPF MVVM. Use it where possible.

In my specific case, something went wrong, so I went out in a different way, since my project is not strict MVVM, so I can use a coded solution.

In the CustomView.xaml name assigned to the column:

 <DataGrid> <DataGrid.Columns> <DataGridTemplateColumn x:Name="MachinesColumn" ... /> ... 

In CustomView.xaml.cs, we have a simple property that directly changes the visibility of a column:

 public Visibility MachinesColumnVisible { get { return MachinesColumn.Visibility; } set { if (value == MachinesColumn.Visibility) return; MachinesColumn.Visibility = value; } } 
0
Mar 20 '14 at 9:22
source share



All Articles