将 DataTrigger 值绑定到此 DataTemplate 实例
Posted
技术标签:
【中文标题】将 DataTrigger 值绑定到此 DataTemplate 实例【英文标题】:Binding a DataTrigger value to this instance of DataTemplate 【发布时间】:2021-11-30 22:05:52 【问题描述】:我有一个ListView
,其项目由ItemTemplate
表示,如下所示:
<ListView dependencyObjects:InterestingItem.Interesting="Binding InterestingItem"
ItemsSource="Binding Quotations" >
<ListView.ItemTemplate>
<DataTemplate>
<Border>
<Grid>
<StackPanel x:Name="NotImportant">
</StackPanel>
<Grid x:Name="HiddenGrid"
Background="Red"
Visibility="Hidden" >
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<Grid.Triggers>
<DataTrigger Binding="Binding Path=DataContext.InterestingItem,
RelativeSource=RelativeSource AncestorType=x:Type ListView "
Value="*this instance here*!">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Grid.Triggers>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListView
有一个附加属性InterestingItem
,它是ListView
中的一项。
我无法连接的是当InterestingItem
与其中一项相同时,第二个Grid
应该变得可见。
我不希望更改并绑定到列表中的实际对象 - 而是让ListView
控制要更改的项目。
我需要的DataTrigger
中的Value
是什么?
【问题讨论】:
【参考方案1】:我需要的 DataTrigger 中的值是什么?
恐怕 XAML 不支持 C# 中的 this
关键字。
您可以使用MultiBinding
和IMultiValueConverter
实现来确定项目是否相等:
<Grid x:Name="HiddenGrid" Background="Red">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding>
<MultiBinding.Converter>
<local:MultiConverter />
</MultiBinding.Converter>
<Binding Path="Binding Path=DataContext.InterestingItem,
RelativeSource=RelativeSource AncestorType=x:Type ListView " />
<Binding Path="Binding" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
转换器:
public class MultiConverter : IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) =>
values != null && values.Length == 2 && values[0] == values[1];
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
请注意,如果您希望能够使用 Style
设置器覆盖该值,则不能将 Grid
的 Visibility
属性设置为本地值。
<Grid x:Name="HiddenGrid" Background="Red" Visibility="Hidden">
【讨论】:
【参考方案2】:您的 XAML 中存在多个问题,并且在概念上会阻止它工作。
要绑定附加属性,您必须使用正确的带括号的语法。
Path="Binding (local:InterestingItem.Interesting), RelativeSource=RelativeSource AncestorType=x:Type ListView"
请参阅Binding path syntax 文档以供参考。
Triggers
属性只支持EventTriggers
,请参阅FrameworkElement.Triggers
。
注意,在一个元素上建立的触发器集合只支持EventTrigger,不支持属性触发器(Trigger)。如果您需要属性触发器,则必须将它们放在样式或模板中,然后直接通过 Style 属性或通过隐式样式引用间接将该样式或模板分配给元素。
您不能绑定DataTrigger
的Value
属性,因为它不是依赖属性。
您当然可以更改绑定类型以公开指示它是否为特殊对象的属性,并使用 DataTrigger
在 XAML 中绑定该属性,类似于此(其中 IsSpecial
是新的 bool
属性)。
<Grid x:Name="HiddenGrid"
Background="Red">
<TextBlock Text="Hidden Grid"/>
<Grid.Style>
<Style TargetType="x:Type Grid">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="Binding IsSpecial" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
如果您想坚持当前的方法,您可以创建一个自定义IMultiValueConverter
,以启用绑定多个属性。它将检查所有绑定值是否相等,否则返回Visibility.Visible
或Visibility.Hidden
。此示例使用 Linq 来检查这一点并支持绑定任意数量的值,但还有许多其他选项。
public class EqualityToVisibilityConverter : IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
if (values is null || values.Length < 2)
return Binding.DoNothing;
return values.Distinct().Count() == 1 ? Visibility.Visible : Visibility.Hidden;
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
throw new InvalidOperationException();
接下来,在ListView
的资源或范围内的任何其他资源字典中实例化转换器,并将Grid
的Visibility
属性绑定到当前项(仅<Binding/>
)和附加属性local:InterestingItem.Interesting
和 MultiBinding
使用转换器将它们转换为 Visibility
。
<ListView local:InterestingItem.Interesting="Binding InterestingItem"
ItemsSource="Binding Quotations">
<ListView.Resources>
<local:EqualityToVisibilityConverter x:Key="EqualityToVisibilityConverter"/>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<Border>
<Grid>
<StackPanel x:Name="NotImportant">
<TextBlock Text="Not Important"/>
</StackPanel>
<Grid x:Name="HiddenGrid"
Background="Red">
<Grid.Visibility>
<MultiBinding Converter="StaticResource EqualityToVisibilityConverter">
<Binding/>
<Binding Path="(local:InterestingItem.Interesting)"
RelativeSource="RelativeSource AncestorType=x:Type ListView"/>
</MultiBinding>
</Grid.Visibility>
<TextBlock Text="Hidden Grid"/>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这里还有两点需要注意。我添加了两个虚拟TextBlock
s,否则结果将不可见,因为面板是空的。用您的内容替换它们。此外,StackPanel
和 Grid
在父 Grid
中都重叠,我不知道这是不是故意的,但您可以通过添加行或列并将元素移动到那里来更改它。
【讨论】:
以上是关于将 DataTrigger 值绑定到此 DataTemplate 实例的主要内容,如果未能解决你的问题,请参考以下文章
DataTrigger.ExistActions 未触发绑定值“null”
将 DataTrigger `Value` 绑定到 `V Model`
DataGrid RowStyle - DataTrigger 中的绑定值