Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide wpf datagrid columns depending on a property

Tags:

I have the following WPF sample 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 the model classes are:

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 2nd datagrid column, if the Flag property is set to false. But it doesn't work. I get the following binding error in the Visual Studio Output window:

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

What is wrong in my code concerning the Visibility attribute?

like image 787
Hulda Avatar asked Jul 28 '11 10:07

Hulda


2 Answers

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.

like image 172
H.B. Avatar answered Oct 02 '22 15:10

H.B.


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}, ...}" /> 
like image 32
AnjumSKhan Avatar answered Oct 02 '22 15:10

AnjumSKhan