WPF 列表框选定项样式(突出显示覆盖数据触发样式)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14088358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Listbox Selected Item Style (Highlighting is Overriding Data-Triggered Style)
提问by Tim Dunne
I am an Access developer moving into .Net and I have a WPF project. Since I am used to subforms in Access, I created user controls to act this way (may be an issue itself, but not something I am addressing at the moment).
我是一名进入 .Net 的 Access 开发人员,我有一个 WPF 项目。由于我习惯于 Access 中的子窗体,因此我创建了用户控件来执行这种操作(本身可能是一个问题,但目前不是我要解决的问题)。
This particular user control (subform) has several listboxes that are bound to objects in the code behind (VB -- I am not getting into that debate either; I am familiar with VBA). These listboxes are bound to a boolean value called "IsAssigned". I created a style to change the items in these listboxes to Greenish or Reddish depending upon that value. This is working.
这个特定的用户控件(子窗体)有几个列表框,它们绑定到后面代码中的对象(VB——我也没有参与那个辩论;我熟悉 VBA)。这些列表框绑定到一个名为“IsAssigned”的布尔值。我创建了一个样式,根据该值将这些列表框中的项目更改为绿色或红色。这是有效的。
I then wanted to change the value to override the window's Highlight behavior and learned about the SystemColors.HighlightColor and ControlBrushKey. The problem is that I want the HighlightColor and ControlBrushKey colors to be dependent upon the "IsAssigned" value. I apparently can't nest triggers unless I am missing someting. In the following code I have the highlight values set to Green just for an illustration of where I am in my understanding of this.
然后我想更改该值以覆盖窗口的突出显示行为并了解 SystemColors.HighlightColor 和 ControlBrushKey。问题是我希望 HighlightColor 和 ControlBrushKey 颜色取决于“IsAssigned”值。除非我遗漏了一些东西,否则我显然无法嵌套触发器。在下面的代码中,我将高亮值设置为绿色,只是为了说明我对此的理解。
So what I want is that when an item is selected, the text is bolded, with a black border, and maintains a solid color of green or red depending on the "IsAssigned" value. When that same item is the highlighted item, I would really like the forecolor to be white and maybe have a thicker border.
所以我想要的是,当一个项目被选中时,文本是粗体的,带有黑色边框,并根据“IsAssigned”值保持绿色或红色的纯色。当同一项目是突出显示的项目时,我真的希望前景色为白色,并且边框可能更粗。
Be gentle -- I am a noob in more ways than one.
温柔点——我在很多方面都是个菜鸟。
<UserControl.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ColorTrueAndFalse">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightColor}" Color="Green" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="BorderBrush" Value="Black" />
</Trigger>
<DataTrigger Binding="{Binding IsAssigned}" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="LightGreen" Offset="0" />
<GradientStop Color="Green" Offset="1" />
<GradientStop Color="LawnGreen" Offset="2" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsAssigned}" Value="False">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="LightCoral" Offset="0.5" />
<GradientStop Color="Coral" Offset="1" />
<GradientStop Color="Red" Offset="2" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
回答by Blachshma
The DataContextof the ListBoxItemis different from the one of the ListBoxitself.
When using {Binding IsAssigned}inside the ListBoxItem's style, you're not using the same DataContextas the ListBoxand therefor you can't find the property.
The DataContextof theListBoxItem与 the oneListBox本身不同。当使用{Binding IsAssigned}内部ListBoxItem的风格,你没有使用相同DataContext的ListBox,并为此你不能找物业。
This can easily fixed by using Relative Binding- for example:
这可以通过使用相对绑定轻松解决- 例如:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}, Path=DataContext.IsAssigned}" Value="true">
This tries to bind to the ListBoxItems' parent. It goes up the Visual Tree until it finds the ListBox and tries to use the former's DataContextproperty to find the IsAssigned.
这会尝试绑定到 ListBoxItems 的父项。它沿着可视树向上移动,直到找到 ListBox 并尝试使用前者的DataContext属性来查找 IsAssigned。
So a complete solution will look something like this:
所以一个完整的解决方案看起来像这样:
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="BorderBrush" Value="Black" />
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}, Path=DataContext.IsAssigned}" Value="true">
<Setter Property="Background">
....
</Setter>
</DataTrigger>
Update- For highlighting:
更新- 突出显示:
First notice the name of the Highlight brush is HighlightBrushKeynot as you wrote:
首先注意高光笔刷的名称HighlightBrushKey和你写的不一样:
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Green" />
Second - Instead of the Triggeryou used, use this DataTriggerto change the selected item's properties:
第二 - 而不是Trigger您使用的,使用它DataTrigger来更改所选项目的属性:
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="BorderBrush" Value="Black" />
</DataTrigger>
回答by Tim Dunne
Well after a lot of pulling out what little hair I have left, and some pointers in the right direction from Blachshma, I came up with a solution. It is mainly based off of the markup found here.
好吧,在拔掉了我剩下的几根头发,并从 Blachshma 那里向正确方向提供了一些指示之后,我想出了一个解决方案。它主要基于此处找到的标记。
The HighlightBrushKey and ControlBrushKey were giving me grief -- I could not get them to recognize the underlying color already set by a data trigger. I could set it to a static color, but nothing dynamic. Perhaps with more time invested this would have worked. Instead, I used the border to set the color in the data trigger and changed the font and opacity of any selected items. The border color still remained the same, even after selecting an item in one listbox and moving away to select another item in another listbox, which is exactly what I wanted.
HighlightBrushKey 和 ControlBrushKey 让我很伤心——我无法让它们识别数据触发器已经设置的底层颜色。我可以将它设置为静态颜色,但没有动态。也许投入更多的时间这会奏效。相反,我使用边框在数据触发器中设置颜色并更改任何选定项目的字体和不透明度。即使在一个列表框中选择一个项目并移开以选择另一个列表框中的另一个项目后,边框颜色仍然保持不变,这正是我想要的。
Here is my XAML (with certain details left out for the sake of brevity):
这是我的 XAML(为简洁起见,省略了某些细节):
<UserControl.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="BorderTrueAndFalse">
<Style.Resources>
<LinearGradientBrush x:Key="TrueBrush" EndPoint="1,0.5" StartPoint="0,0.5">
...
</LinearGradientBrush>
<LinearGradientBrush x:Key="FalseBrush" EndPoint="0,0.5" StartPoint="1,0.5">
...
</LinearGradientBrush>
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Padding="2" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsAssigned}" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource TrueBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsAssigned}" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource FalseBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="Opacity" Value=".8"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
Of course, I believe that I am ony 80% sure of what is going on here, but the process has given me a deeper understanding of binding, triggers, styles, templates, and why Access stuff is developed so much faster! Maybe someday I will set the text to spin, flash, and get up to do a little jig, but for now I am a happy camper.
当然,我相信我对这里发生的事情只有 80% 的把握,但是这个过程让我对绑定、触发器、样式、模板以及为什么 Access 的东西开发得如此之快有了更深入的了解!也许有一天我会把文字设置为旋转、闪烁,然后起床做一个小夹具,但现在我是一个快乐的露营者。

