简体   繁体   English

如何根据属性隐藏wpf datagrid列

[英]How to hide wpf datagrid columns depending on a property

I have the following WPF sample program: 我有以下WPF示例程序:

Xaml: 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. 如您所见,如果Flag属性设置为false,我想隐藏第二个datagrid列。 But it doesn't work. 但它不起作用。 I get the following binding error in the Visual Studio Output window: 我在Visual Studio输出窗口中收到以下绑定错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Window',AncestorLevel ='1''。 BindingExpression:Path=DataContext.Flag; BindingExpression:路径= DataContext.Flag; DataItem=null; 的DataItem = NULL; target element is 'DataGridTextColumn' (HashCode=44856655); target元素是'DataGridTextColumn'(HashCode = 44856655); target property is 'Visibility' (type 'Visibility') 目标属性是“可见性”(类型“可见性”)

What is wrong in my code concerning the Visibility attribute? 我的代码中有关Visibility属性的错误是什么?

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. 在DataGrid的列是不会出现在可视化树的抽象对象,因此不能使用RelativeSource -结合, ElementName将不工作,要么因为它不会找到一个管理FrameworkContentElement上让你实物绑定的。

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: 一种方法是通过Sourcex:Reference ,为此您需要命名窗口并将列移动到其资源以避免周期性依赖性错误:

<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 . 我更喜欢使用Freezable的更优雅的方法。

<Window.Resources>

    <DiscreteObjectKeyFrame x:Key="FlagKey" Value="{Binding Flag}"/>

</Window.Resources>


<DataGridTextColumn ... Visibility="{Binding Value, Source={StaticResource FlagKey}, ...}" />

Visibility on DataGridTextColumn is not a DependencyProperty and can't be databound. DataGridTextColumn上的可见性不是DependencyProperty,也不能是数据绑定。 Use a DataGridTemplateColumn and bind the visibility of the controls within the template. 使用DataGridTemplateColumn并绑定模板中控件的可见性。

Edit: Actually, this statement only applies to silverlight. 编辑:实际上,此声明仅适用于silverlight。 See this other SO question for further details. 有关详细信息,请参阅此其他SO问题。

How to bind DataGridColumn.Visibility? 如何绑定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? 我怎样才能最容易地确定属性是否是依赖属性?

Solution proposed by HB is really good and has true WPF MVVM spirit. HB提出的解决方案非常好,并且具有真正的WPF MVVM精神。 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. 在我的特殊情况下出了问题所以我以不同的方式出来,因为我的项目不是严格的MVVM,所以我可以使用编码解决方案。

In CustomView.xaml name assigned to column: 在分配给列的CustomView.xaml名称中:

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

In CustomView.xaml.cs we have a simple property which directly changes visibility of column: 在CustomView.xaml.cs中,我们有一个简单的属性,可直接更改列的可见性:

public Visibility MachinesColumnVisible
{
    get { return MachinesColumn.Visibility; }
    set
    {
        if (value == MachinesColumn.Visibility)
            return;
        MachinesColumn.Visibility = value;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM