要动态控制 DataGridTextColumn 是否显示,不能用普通触发器或直接绑定,因为列不在可视树中。做法是:
- 给列挂"可绑定的可见性"附加属性;
- 用绑定把该属性连到一个状态值(如 ViewModel 的 SelectedTabItemData.State 或当前选中行的 State);
- 用转换器把状态转成 Visible/Collapsed。
示例:
xaml
<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
csharp
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
csharp
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
csharp
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。
了解更多
System.Windows.Controls 命名空间 | Microsoft Learn
控件库 - WPF .NET Framework | Microsoft Learn
使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn
HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频