如何根据属性隐藏wpf datagrid列

Posted

技术标签:

【中文标题】如何根据属性隐藏wpf datagrid列【英文标题】:How to hide wpf datagrid columns depending on a property 【发布时间】:2011-10-15 00:38:06 【问题描述】:

我有以下 WPF 示例程序:

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>

后面的代码:

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;            
    

模型类是:

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; 

如您所见,如果 Flag 属性设置为 false,我想隐藏第二个数据网格列。但它不起作用。我在 Visual Studio 输出窗口中收到以下绑定错误:

System.Windows.Data 错误:4:找不到绑定源 参考'RelativeSource FindAncestor, AncestorType='System.Windows.Window',AncestorLevel='1''。 BindingExpression:Path=DataContext.Flag;数据项=空;目标元素 是 'DataGridTextColumn' (HashCode=44856655);目标属性是 “可见性”(类型“可见性”)

关于Visibility 属性的代码有什么问题?

【问题讨论】:

【参考方案1】:

如果您要自动生成列,则可以使用一个事件:

https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.datagrid.autogeneratingcolumn?view=net-5.0

我将更改为自动生成的列和此事件以解决几个问题!也可以用来改变列上的Header。

【讨论】:

鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防外部资源无法访问或永久离线。【参考方案2】:

我更喜欢使用Freezable 的更优雅的方法。

<Window.Resources>

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

</Window.Resources>


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

【讨论】:

AnjumSKhan :确实非常好。干净优雅。谢谢 这也适用于绑定代理不起作用的情况。刚刚试了一下——谢谢! 在 .Net 5 中测试过,效果很好。另外,它允许我基于一个公共属性一次隐藏几列。简单的智能解决方案。额外提示:如果要将布尔值转换为可见性,请使用 DiscreteObjectKeyFrame.Value 转换器:&lt;DiscreteObjectKeyFrame x:Key="FlagKey" Value="Binding Flag, Converter=StaticResource BooleanToVisibilityConverter" /&gt;【参考方案3】:

H.B. 提出的解决方案。真的很好,有真正的 WPF MVVM 精神。尽可能使用它。

在我的特殊情况下出了点问题,所以我想出了不同的方法,因为我的项目不是严格的 MVVM,所以我可以使用编码解决方案。

在 CustomView.xaml 中分配给列的名称:

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

在 CustomView.xaml.cs 中,我们有一个简单的属性可以直接改变列的可见性:

public Visibility MachinesColumnVisible

    get  return MachinesColumn.Visibility; 
    set
    
        if (value == MachinesColumn.Visibility)
            return;
        MachinesColumn.Visibility = value;
    

【讨论】:

【参考方案4】:

DataGridTextColumn 上的可见性不是 DependencyProperty,不能进行数据绑定。使用 DataGridTemplateColumn 并绑定模板内控件的可见性。

编辑:实际上,此声明仅适用于 Silverlight。有关详细信息,请参阅此其他 SO 问题。

How to bind DataGridColumn.Visibility?

我在这里询问了判断属性是否为依赖项的最简单方法。

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

【讨论】:

感谢您的回答。你能告诉我如何在 Xaml 中识别一个属性是否是依赖属性吗? 我得到一个 绑定错误 令人困惑(请参阅我的编辑)。看起来 WPF 会尝试将 Visibility 绑定到属性。如果一个属性根本无法绑定,我预计会出现不同的错误——比如“无法绑定”之类的。 其实是DP,否则会编译出错。 @H.B.我的错。这看起来像是 Silverlight 和 WPF 之间的区别。 感谢您的进一步解释!【参考方案5】:

数据网格中的列是一个抽象对象,它不会出现在可视化树中,因此您不能使用RelativeSource-binding,ElementName 也不起作用,因为它找不到管理 FrameworkContentElement,所以您在一种绑定。

一种可行的方法是通过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"/>
                <!-- ... -->

非常有趣。

【讨论】:

我知道,我参加聚会有点晚了,但是谢谢,伙计!附言我讨厌 DataGrid 开发者。 自从我从 .NET 4 升级到 4.5.2 后,我似乎无法让它工作。有谁知道为什么? @CamHart:你知道如何调试绑定吗? @H.B.不,我没有。我试图启动第二个 VS,并附加到第一个 VS 上运行的进程。但我永远无法触发任何错误。不过我确实找到了解决方案,***.com/questions/34817417/…。 @H.B.如果绑定是在单独的 xaml 文件的单独 ResourceDictionary 中的

以上是关于如何根据属性隐藏wpf datagrid列的主要内容,如果未能解决你的问题,请参考以下文章

如何隐藏 WPF DataGrid 中的列标题?

WPF中DataGrid列根据条件隐藏

如何使用 MVVM 自动隐藏 WPF 中的 DataGrid 列? [复制]

怎么知道用户选择的wpf的datagrid的哪一列

c# wpf datagrid 模板列修改某个单元格,更新所选行另一个单元格的值,如何做到呢?

找不到将Wpf DataGrid列绑定到属性的方法[关闭]