【笔记】WPF中如何的动态设置DataGridTextColumn是否显示
要动态控制 DataGridTextColumn 是否显示,不能用普通触发器或直接绑定,因为列不在可视树中。做法是:
- 给列挂“可绑定的可见性”附加属性;
- 用绑定把该属性连到一个状态值(如 ViewModel 的 SelectedTabItemData.State 或当前选中行的 State);
- 用转换器把状态转成 Visible/Collapsed。
示例:
<UserControl x:Class="H.Sxb.Modules.Bill.View.OrderBillControl"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:b="http://schemas.microsoft.com/xaml/behaviors"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:H.Sxb.Modules.Bill.View"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:sys="clr-namespace:System;assembly=mscorlib"mc:Ignorable="d"><UserControl.Resources><local:IntInSetToVisibilityConverter x:Key="IntInSetToVisibilityConverter" /><local:BindingProxy x:Key="dgProxy" Data="{Binding}" /></UserControl.Resources><!-- ... --><DataGrid x:Name="dg"ItemsSource="{Binding PageResponse.Items}"><DataGrid.Columns><!-- 顶部表格:当 State 为 1/2/3 显示“实发金额”,为 2/3 显示“收货金额” --><DataGridTextColumn Binding="{Binding MinusAmount}"Header="实发金额"local:DataGridColumnExtensions.BindableVisibility="{Binding Data.SelectedTabItemData.State,Source={StaticResource dgProxy},Converter={StaticResource IntInSetToVisibilityConverter},ConverterParameter=1,2,3}" /><DataGridTextColumn Binding="{Binding ReceivableAmount}"Header="收获金额"local:DataGridColumnExtensions.BindableVisibility="{Binding Data.SelectedTabItemData.State,Source={StaticResource dgProxy},Converter={StaticResource IntInSetToVisibilityConverter},ConverterParameter=2,3}" /><!-- 其余列... --></DataGrid.Columns></DataGrid>
</UserControl>
- IntInSetToVisibilityConverter
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;namespace H.Sxb.Modules.Bill.View
{public class IntInSetToVisibilityConverter : IValueConverter{public bool Invert { get; set; }public object Convert(object value, Type targetType, object parameter, CultureInfo culture){var text = parameter?.ToString() ?? string.Empty;var set = text.Split(new[] { ' '}, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray();var val = value?.ToString();var match = set.Any(s => string.Equals(s, val, StringComparison.OrdinalIgnoreCase));if (Invert) match = !match;return match ? Visibility.Visible : Visibility.Collapsed;}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>Binding.DoNothing;}
}
- DataGridColumnExtensions
using System.Windows;
using System.Windows.Controls;namespace H.Sxb.Modules.Bill.View
{public static class DataGridColumnExtensions{public static readonly DependencyProperty BindableVisibilityProperty =DependencyProperty.RegisterAttached("BindableVisibility",typeof(Visibility),typeof(DataGridColumnExtensions),new PropertyMetadata(Visibility.Visible, OnBindableVisibilityChanged));public static void SetBindableVisibility(DependencyObject obj, Visibility value) =>obj.SetValue(BindableVisibilityProperty, value);public static Visibility GetBindableVisibility(DependencyObject obj) =>(Visibility)obj.GetValue(BindableVisibilityProperty);private static void OnBindableVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (d is DataGridColumn column && e.NewValue is Visibility v)column.Visibility = v;}}
}
- BindingProxy
using System.Windows;namespace H.Sxb.Modules.Bill.View
{// Freezable proxy to expose DataContext into places not in the visual tree (e.g., DataGridColumn)public class BindingProxy : Freezable{public object Data{get => GetValue(DataProperty);set => SetValue(DataProperty, value);}public static readonly DependencyProperty DataProperty =DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));protected override Freezable CreateInstanceCore() => new BindingProxy();}
}
要点
- DataGridColumn 不在可视树,必须用附加属性设置列的 Visibility。请确保使用命名空间前缀:local:DataGridColumnExtensions.BindableVisibility。
- 绑定源可用 BindingProxy 暴露的 DataContext(你已加 dgProxy,继续沿用即可)。
- ConverterParameter 建议逗号分隔(1,2,3)。如果你的 IntInSetToVisibilityConverter 已实现空格分隔,也可保持空格。
- 若需“按行”显示/隐藏,请改用 DataGridTemplateColumn,在 CellTemplate 内用 DataTrigger 控制单元内容的 Visibility。
了解更多
DataGridColumn
System.Windows.Controls 命名空间 | Microsoft Learn
控件库 - WPF .NET Framework | Microsoft Learn
WPF 介绍 | Microsoft Learn
使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn
https://github.com/HeBianGu
HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频
GitHub - HeBianGu/WPF-Control: WPF轻量控件和皮肤库
GitHub - HeBianGu/WPF-ControlBase: Wpf封装的自定义控件资源库