如何通过DataGrid依赖属性绑定ItemsSource列实现DataTrigger
问题:通过DataGrid依赖属性绑定ItemsSource列实现DataTrigger生效
现有无需依赖属性的可行实现
<Style TargetType="DataGridRow"> <Style.Triggers> <DataTrigger Binding="{Binding NAME}" Value="{x:Null}"> <Setter Property="Visibility" Value="Collapsed"/> </DataTrigger> </Style.Triggers> </Style>
期望的依赖属性实现方式
<Style TargetType="DataGridRow"> <Style.Triggers> <DataTrigger Binding="{Binding HideRow, ElementName=_myGrid}" Value="{x:Null}"> <Setter Property="Visibility" Value="Collapsed"/> </DataTrigger> </Style.Triggers> </Style>
自定义DataGrid的依赖属性代码
public static DependencyProperty HideRowProperty = DependencyProperty.Register("HideRow", typeof(PersonsModel), typeof(My_DataGrid), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); ///<summary>Property for hiding rows, based on column name</summary> public PersonsModel HideRow { get { return (PersonsModel)GetValue(HideRowProperty); } set { SetValue(HideRowProperty, value); } }
尝试的XAML绑定代码
<ctl:My_DataGrid ItemsSource="{Binding Persons}" HideRow="{Binding Persons.NAME}">
错误信息
BindingExpression路径错误:在对象“ObservableCollection`1”上未找到“NAME”属性。
修正方案
1. 调整依赖属性设计
将依赖属性改为存储要检查的属性名称(字符串类型),而非实体对象:
public static DependencyProperty HideRowProperty = DependencyProperty.Register("HideRow", typeof(string), typeof(My_DataGrid), new FrameworkPropertyMetadata(null)); ///<summary>要检查的属性名称,当该属性值为Null时隐藏行</summary> public string HideRow { get { return (string)GetValue(HideRowProperty); } set { SetValue(HideRowProperty, value); } }
2. 实现属性路径转换器
创建转换器,根据传入的属性名称动态获取数据项的属性值:
public class PropertyPathConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Length != 2 || values[0] == null || values[1] == null) return null; var dataItem = values[0]; var propertyName = values[1].ToString(); var propertyInfo = dataItem.GetType().GetProperty(propertyName); return propertyInfo?.GetValue(dataItem); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
3. 修改XAML样式与绑定
先在资源中声明转换器:
<Window.Resources> <local:PropertyPathConverter x:Key="PropertyPathConverter"/> </Window.Resources>
再调整DataGridRow的Style,通过多值绑定关联当前行数据与DataGrid的依赖属性:
<Style TargetType="DataGridRow"> <Style.Triggers> <DataTrigger Value="{x:Null}"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource PropertyPathConverter}"> <Binding/> <!-- 绑定当前行的PersonsModel实例 --> <Binding Path="HideRow" ElementName="_myGrid"/> <!-- 绑定DataGrid的依赖属性 --> </MultiBinding> </DataTrigger.Binding> <Setter Property="Visibility" Value="Collapsed"/> </DataTrigger> </Style.Triggers> </Style>
4. 修正DataGrid的绑定配置
<ctl:My_DataGrid x:Name="_myGrid" ItemsSource="{Binding Persons}" HideRow="NAME">
问题根源说明
- 原绑定
HideRow="{Binding Persons.NAME}"错误:Persons是ObservableCollection<PersonsModel>集合对象,本身没有NAME属性,只有集合内的单个PersonsModel实例才具备该属性。 - 原依赖属性类型为
PersonsModel,无法实现动态指定要检查的列,改为字符串类型存储属性名更符合需求。 - DataGridRow的DataContext是集合中的单个
PersonsModel实例,因此需要通过多值绑定同时获取当前行数据和DataGrid的依赖属性值,再通过转换器完成属性值的动态判断。
内容的提问来源于stack exchange,提问作者Lucy82
相关产品推荐
相关产品推荐

