将 DataTrigger 值绑定到此 DataTemplate 实例



我有一个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是什么?

XAML 中存在多个问题,从概念上讲,这些问题会阻止它工作。

  • 若要绑定附加属性,必须使用带括号的正确语法。

    Path="{Binding (local:InterestingItem.Interesting), RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
    

    有关参考,请参阅绑定路径语法文档。

  • Triggers属性仅支持EventTriggers,请参阅FrameworkElement.Triggers

    请注意,在元素上建立的触发器集合仅支持 EventTrigger,不支持属性触发器 (Trigger)。如果需要属性触发器,则必须将这些触发器放置在样式或模板中,然后直接通过 Style 属性或通过隐式样式引用间接将该样式或模板分配给元素。

  • 你不能绑定DataTriggerValue属性,因为它不是依赖属性。

当然,您可以更改绑定类型以公开指示它是否为特殊对象的属性,并使用类似于以下内容的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.VisibleVisibility.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的资源或范围内的任何其他资源字典中实例化转换器,并将GridVisibility属性绑定到当前项(仅<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,否则结果将不可见,因为面板是空的。将它们替换为您的内容。此外,StackPanelGrid在父Grid中都重叠,我不知道这是否是故意的,但是您可以通过添加行或列并将元素移动到那里来更改它。

我需要的数据

触发器中的值是多少?

恐怕 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();
}

请注意,如果希望能够使用Stylesetter 重写该值,则不能将GridVisibility属性设置为本地值。

<Grid x:Name="HiddenGrid" Background="Red" Visibility="Hidden">

最新更新