基于视图模型类型的边框触发器不起作用
Border trigger based on viewmodel type doesn't work
我有一个 MainView - 它有一个 属性 "ViewModel" - 当我将此 ViewModel 更改为不同类型时,我将 window 上的数据上下文更新为特定的视图模型然后我使用 ContentControl 和 DataTemplate 来更改一些内容 - 这一切都有效。
现在我尝试创建一个触发器来根据视图模型类型更改边框的背景 - 我想到了这个:
<Border Background="#3f3f3f" CornerRadius="10">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Type viewmodels:AllBeadsViewModel}">
<Setter Property="Background" Value="White"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="10">
<Image Height="32" Source="/Images/Icons/bookmark-1.png" Margin="0,0,0,5" />
<TextBlock Text="All Beads" VerticalAlignment="Center" Foreground="White" />
</StackPanel>
</Border>
我使用 WPF Inspector 尝试确保数据上下文正确 (AllBeadsViewModel) 并且 setter 描述正确 - 一切似乎都匹配。我在这里做错了什么?
您发布的 XAML 中有两个问题。
第一个是紧迫的问题,如何根据对象的类型设置触发器。您的 <DataTrigger/>
元素引用 Binding
属性 中的当前数据上下文,然后引用 Value
中对象的 type ] 属性。因此,这要求 WPF 将 数据上下文对象本身 与 System.Type
的实例进行比较。由于您的数据上下文对象实际上不是一种类型,因此永远不会触发。
要解决这个问题,您需要一种机制来比较当前数据上下文对象的 类型 与 AllBeadsViewModel
类型。与 WPF 的典型情况一样,有几个不同的选项。但是恕我直言,最简单的方法之一是为触发器的绑定编写一个 IValueConverter
,它只是 returns 绑定值上 GetType()
的结果。
现在,完成您发布的 XAML 仍然不会根据触发器更新边框的背景颜色,因为 Background
属性 在 <Border/>
元素 takes precedence over any setter found in a style。要解决此问题,您需要删除显式 属性 值分配,并将其替换为样式本身中的 <Setter/>
元素:
<Border CornerRadius="10">
<Border.Style>
<p:Style TargetType="Border">
<Setter Property="Background" Value="#3f3f3f"/>
<!-- etc. -->
</p:Style>
</Border.Style>
<!-- etc. -->
</Border>
(您可以忽略我添加到上面 <Style/>
元素的 p:
XML 命名空间……那只是因为 XML/XAML 的 Stack Overflow 代码格式化程序被不合格的 <Style/>
元素混淆并停止格式化为 XML 直到元素关闭。)
另请参阅 WPF Trigger won't set property if set in Element,了解关于您 XAML 的第二个 aspect/problem 的讨论。
我有一个 MainView - 它有一个 属性 "ViewModel" - 当我将此 ViewModel 更改为不同类型时,我将 window 上的数据上下文更新为特定的视图模型然后我使用 ContentControl 和 DataTemplate 来更改一些内容 - 这一切都有效。
现在我尝试创建一个触发器来根据视图模型类型更改边框的背景 - 我想到了这个:
<Border Background="#3f3f3f" CornerRadius="10">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Type viewmodels:AllBeadsViewModel}">
<Setter Property="Background" Value="White"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="10">
<Image Height="32" Source="/Images/Icons/bookmark-1.png" Margin="0,0,0,5" />
<TextBlock Text="All Beads" VerticalAlignment="Center" Foreground="White" />
</StackPanel>
</Border>
我使用 WPF Inspector 尝试确保数据上下文正确 (AllBeadsViewModel) 并且 setter 描述正确 - 一切似乎都匹配。我在这里做错了什么?
您发布的 XAML 中有两个问题。
第一个是紧迫的问题,如何根据对象的类型设置触发器。您的 <DataTrigger/>
元素引用 Binding
属性 中的当前数据上下文,然后引用 Value
中对象的 type ] 属性。因此,这要求 WPF 将 数据上下文对象本身 与 System.Type
的实例进行比较。由于您的数据上下文对象实际上不是一种类型,因此永远不会触发。
要解决这个问题,您需要一种机制来比较当前数据上下文对象的 类型 与 AllBeadsViewModel
类型。与 WPF 的典型情况一样,有几个不同的选项。但是恕我直言,最简单的方法之一是为触发器的绑定编写一个 IValueConverter
,它只是 returns 绑定值上 GetType()
的结果。
现在,完成您发布的 XAML 仍然不会根据触发器更新边框的背景颜色,因为 Background
属性 在 <Border/>
元素 takes precedence over any setter found in a style。要解决此问题,您需要删除显式 属性 值分配,并将其替换为样式本身中的 <Setter/>
元素:
<Border CornerRadius="10">
<Border.Style>
<p:Style TargetType="Border">
<Setter Property="Background" Value="#3f3f3f"/>
<!-- etc. -->
</p:Style>
</Border.Style>
<!-- etc. -->
</Border>
(您可以忽略我添加到上面 <Style/>
元素的 p:
XML 命名空间……那只是因为 XML/XAML 的 Stack Overflow 代码格式化程序被不合格的 <Style/>
元素混淆并停止格式化为 XML 直到元素关闭。)
另请参阅 WPF Trigger won't set property if set in Element,了解关于您 XAML 的第二个 aspect/problem 的讨论。