C# 基于viewmodel类型的边框触发器不';行不通
我有一个MainView,它有一个属性“ViewModel”-当我将这个ViewModel更改为不同的类型时,我将窗口上的datacontext设置为特定的ViewModel,然后我使用ContentControl和DataTemplate来更改一些内容-这一切都有效 现在,我尝试创建一个触发器,根据viewmodel类型更改边框的背景-我想到了以下方法:C# 基于viewmodel类型的边框触发器不';行不通,c#,wpf,mvvm,binding,datatrigger,C#,Wpf,Mvvm,Binding,Datatrigger,我有一个MainView,它有一个属性“ViewModel”-当我将这个ViewModel更改为不同的类型时,我将窗口上的datacontext设置为特定的ViewModel,然后我使用ContentControl和DataTemplate来更改一些内容-这一切都有效 现在,我尝试创建一个触发器,根据viewmodel类型更改边框的背景-我想到了以下方法: <Border Background="#3f3f3f" CornerRadius="10"> <Border.S
<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检查器来尝试并确保datacontext是正确的(AllBeadViewModel),并且setter被正确地描述了——所有这些看起来都是匹配的。我做错了什么?您发布的XAML中有两个问题 第一个是直接的问题,如何根据对象的类型设置触发器。您的
元素在绑定
属性中引用当前数据上下文,然后在值
属性中引用对象的类型。因此,这要求WPF将数据上下文对象本身与System.Type
的实例进行比较。因为您的数据上下文对象实际上不是一个类型,所以它永远不会触发
要解决这个问题,您需要一种机制来比较当前数据上下文对象的类型与AllBeadsViewModel
类型。与WPF的典型情况一样,有几个不同的选项。但是,最简单的方法之一是为触发器的绑定编写一个IValueConverter
,它只返回绑定值的GetType()
结果
现在,您发布的XAML仍然不会基于触发器更新边框的背景颜色,因为
元素中背景属性的显式设置。要解决此问题,您需要删除显式属性值赋值,并在样式本身中将其替换为
元素:
<Border CornerRadius="10">
<Border.Style>
<p:Style TargetType="Border">
<Setter Property="Background" Value="#3f3f3f"/>
<!-- etc. -->
</p:Style>
</Border.Style>
<!-- etc. -->
</Border>
(您可以忽略我添加到上面
元素中的p:
XML名称空间……这是因为XML/XAML的堆栈溢出代码格式化程序被不合格的
元素弄糊涂了,并停止格式化为XML,直到元素关闭。)
有关XAML的第二个方面/问题的讨论,请参见。您发布的XAML中有两个问题
第一个是直接的问题,如何根据对象的类型设置触发器。您的
元素在绑定
属性中引用当前数据上下文,然后在值
属性中引用对象的类型。因此,这要求WPF将数据上下文对象本身与System.Type
的实例进行比较。因为您的数据上下文对象实际上不是一个类型,所以它永远不会触发
要解决这个问题,您需要一种机制来比较当前数据上下文对象的类型与AllBeadsViewModel
类型。与WPF的典型情况一样,有几个不同的选项。但是,最简单的方法之一是为触发器的绑定编写一个IValueConverter
,它只返回绑定值的GetType()
结果
现在,您发布的XAML仍然不会基于触发器更新边框的背景颜色,因为
元素中背景属性的显式设置。要解决此问题,您需要删除显式属性值赋值,并在样式本身中将其替换为
元素:
<Border CornerRadius="10">
<Border.Style>
<p:Style TargetType="Border">
<Setter Property="Background" Value="#3f3f3f"/>
<!-- etc. -->
</p:Style>
</Border.Style>
<!-- etc. -->
</Border>
(您可以忽略我添加到上面
元素中的p:
XML名称空间……这是因为XML/XAML的堆栈溢出代码格式化程序被不合格的
元素弄糊涂了,并停止格式化为XML,直到元素关闭。)
有关XAML的第二个方面/问题的讨论,请参见。如果不清楚地显示您正在尝试做什么,什么不起作用,以及您到底想要什么,就不可能确切地知道什么是好的答案。但是,在您发布的代码中,您似乎正在将对象本身与System.Type
的实例进行比较。除非您的对象是类型
,否则将永远不会成功。相反,您可能希望为绑定编写一个转换器,它调用对象上的GetType()
(即将对象转换为其类型)。“那么比较就有意义了。”彼得杜尼奥谢谢你的回答。真的很难知道要在这个问题上输入多少信息。我当然可以链接我的全部源代码,但那只会产生太多的噪音。因此,我的Window.DataContext是一个类,一个AllBeadViewModel或EditBeadViewModel-基于它是哪一个,我想要一个边框切换背景色。所以是的,我在检查类型。我明白你的意思。所以我做了一个转换器。首先,我尝试将value.GetType()与{x:Type viewmodels:AllBeadsViewModel}匹配-这不起作用-因此我尝试将value.GetType().Name与“AllBeadsViewModel”匹配-仍然没有效果请记住,元素中的显式值集将覆盖在样式中设置它的任何尝试。除了转换器之外,您还应该从边框元素声明中删除背景=“#3f3f”
,并将
添加到样式中。@PeterDuniho就是这样做的!我没有意识到您不能有这样的初始属性,但您必须添加一个setter。如果你给出一个“答案”,我会接受:)如果你不清楚你想做什么,什么不起作用,以及你到底想要什么,你就不可能确切地知道一个好的答案会是什么