wpf 列表框鼠标悬停背景色

7tofc5zh  于 2023-02-13  发布在  其他
关注(0)|答案(2)|浏览(230)

我遇到的问题是,为背景着色的MouseOver触发器在选定的行上失败。
对于任何未选中的行,鼠标悬停时背景变为蓝色。
但所选行没有蓝色背景。
点击一行,然后背景蓝色消失。
我还在列表框中尝试了该样式。

<Window x:Class="ListBoxLastIntoView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="0"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListBox Grid.Row="1" Grid.ColumnSpan="2" x:Name="lvMVitems" 
            ItemsSource="{Binding Mode=OneWay}" 
            ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="300">
            <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Style.Resources>
                        <!-- Background of selected item when focussed -->
                        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                        <!-- Background of selected item when not focussed -->
                        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />
                    </Style.Resources>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="LightSteelBlue" />
                        </Trigger>
                    </Style.Triggers>
                </Style>                 
            </ListBox.Resources>
            <!--<ListBox.ItemContainerStyle>               
            </ListBox.ItemContainerStyle>-->
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{TemplateBinding Content}" Background="Orange" Margin="20,2,2,2">
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

namespace ListBoxLastIntoView
{
    public partial class MainWindow : Window
    {
        private string lorum = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
        private List<string> lorums = new List<string>();
        public MainWindow()
        {
            for (int i = 1; i < 100; i++) lorums.Add(i.ToString() + " " + lorum);           
            InitializeComponent();
            //lb.ItemsSource = lorums;
            lvMVitems.ItemsSource = lorums;
        }
    }
}
z9zf31ra

z9zf31ra1#

如果查看ListBoxItem的默认模板,您将看到**IsMouseOver触发器在IsSelected触发器之前应用**。由于DataTrigger是从上到下计算的,最后一个触发器总是获胜,并将ListBoxItemBackground设置为Transparent(在您的情况下)。
如果你想覆盖该行为,你必须覆盖默认模板并更改触发器的顺序。下面是一个示例,展示了如何做到这一点,你可以根据需要更改背景颜色和边框画笔:

<Style TargetType="ListBoxItem">
  <Setter Property="Template">
     <Setter.Value>
       <ControlTemplate TargetType="ListBoxItem">
          <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                  Padding="{TemplateBinding Control.Padding}"
                  BorderBrush="{TemplateBinding Border.BorderBrush}"
                  Background="{TemplateBinding Panel.Background}"
                  Name="Bd"
                  SnapsToDevicePixels="True">
             <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                               ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
                               ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
                               HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
                               VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
                               SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
          </Border>
          <ControlTemplate.Triggers>
             <MultiTrigger>
                <MultiTrigger.Conditions>
                  <Condition Property="Selector.IsSelectionActive" Value="False"/>
                  <Condition Property="Selector.IsSelected" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter Property="Panel.Background" TargetName="Bd" 
                        Value="Transparent"/>
                <Setter Property="Border.BorderBrush" TargetName="Bd">
                   <Setter.Value>
                     <SolidColorBrush>#FFDADADA</SolidColorBrush>
                   </Setter.Value>
                </Setter>
             </MultiTrigger>
             <MultiTrigger>
               <MultiTrigger.Conditions>
                 <Condition Property="Selector.IsSelectionActive" Value="True"/>
                 <Condition Property="Selector.IsSelected" Value="True"/>
               </MultiTrigger.Conditions>
               <Setter Property="Panel.Background" TargetName="Bd" Value="Transparent"/>
               <Setter Property="Border.BorderBrush" TargetName="Bd">
                 <Setter.Value>
                   <SolidColorBrush>#FF26A0DA</SolidColorBrush>
                 </Setter.Value>
               </Setter>
             </MultiTrigger>
             <Trigger Property="UIElement.IsMouseOver" Value="True">
               <Setter Property="Panel.Background" TargetName="Bd" 
                       Value="LightSteelBlue"/>
               <Setter Property="Border.BorderBrush" TargetName="Bd">
                 <Setter.Value>
                   <SolidColorBrush>#A826A0DA</SolidColorBrush>
                 </Setter.Value>
               </Setter>
             </Trigger>
             <Trigger Property="UIElement.IsEnabled" Value="False">
               <Setter Property="TextElement.Foreground" TargetName="Bd">
                 <Setter.Value>
                   <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                 </Setter.Value>
               </Setter>
             </Trigger>
          </ControlTemplate.Triggers>
       </ControlTemplate>
     </Setter.Value>
   </Setter>
</Style>
    • 更新**

也许我应该多解释一下我上面的Assert。
首先,我有Windows 8供我使用,Windows 7和Windows 8之间的默认模板有很大不同。对于Windows 8,主题样式是从PresentationFramework.Aero2.dll中选取的,因此默认模板可能与PresentationFramework.Aero.dll(用于Windows 7和更早版本)下的主题样式不同。
我在上面贴了我从Aero2.dll得到的默认模板。正如你所看到的,它没有使用HighlightBrushKey,所以覆盖HighlightBrushKey的建议在这种情况下不起作用。(这就是为什么我不喜欢覆盖系统画笔,因为它可能不适用于使用其他主题样式的模板)。
根据戴夫的回答
样式触发器优先于模板触发器,所以不管模板触发器是在列表的第一个还是最后一个位置。
我同意Style触发器优先于模板触发器。但是,我在回答中提到的是当您没有使用任何Style触发器而只是在模板中提供值时的情况。在默认模板中,MouseOver触发器位于顶部,SelectedItem触发器位于其下方。因此,在这种情况下,顺序确实很重要。您可以通过向上移动触发器并删除所有Style触发器来验证这一点。
关于
我不确定Rohit发给你的样式是否是ListBoxItem样式的完整副本。似乎缺少样式设置器。我猜他只是发给你模板。
我已经发布了ListBoxItem的完整模板下找到Aero2.dll,显然可能会根据主题风格不同。
我使用XamlWriter.Save(listBoxItem.Template, xmlwrite);获得样式

kqlmhetl

kqlmhetl2#

你有一个有趣的问题。我也有一段时间前写一个主题。
问题不在于触发器的顺序,也不在于哪个触发器在底部,哪个不在底部。
样式触发器优先于模板触发器,所以不管模板触发器是在列表的第一个还是最后一个位置。
你遇到的问题在wpf中是非常罕见的,在你的例子中,隐式样式的触发器被简单地忽略了,因为border的背景与模板化父元素的背景不匹配。
在您的情况下,当is selected属性为true时,触发器由microsoft内部调用。在触发器内部,直接在名称为“Bd”的边框元素上设置背景色,而不是在模板化父元素上设置背景色。
结果是有两种不同的背景。
为了让这一切变得简单,您需要运行以下代码:

<Style TargetType="ListBoxItem">
   <Style.Triggers>
       <Trigger Property="IsMouseOver" Value="True">
           <Setter Property="Background" Value="LightSteelBlue" />
       </Trigger>
   </Style.Triggers>
</Style>

在内部,这是微软的风格。

<MultiTrigger>
   <MultiTrigger.Conditions>
     <Condition Property="Selector.IsSelectionActive" Value="True"/>
     <Condition Property="Selector.IsSelected" Value="True"/>
   </MultiTrigger.Conditions>
   <Setter Property="Background" TargetName="Bd" Value="Blue"/>
 </MultiTrigger>

边框“Bd”背景得到一个新的值,但是你的风格的鼠标在上面触发了主模板的父背景。因此你最终有两个不同的背景。
这是微软应该采取的正确做法!

<MultiTrigger>
   <MultiTrigger.Conditions>
     <Condition Property="Selector.IsSelectionActive" Value="True"/>
     <Condition Property="Selector.IsSelected" Value="True"/>
   </MultiTrigger.Conditions>
   <Setter Property="Background" Value="Blue"/>
 </MultiTrigger>

这是<Setter Property="Background" Value="Blue"/>线,使大的变化。
用我展示给你的方法,你最终不会有两个不同的背景。
现在你知道了内部出了什么问题,让我们进入最重要的部分,如何解决这个问题。
解决方案是......在这一点上,我和Rohit同意相同的问题解决方法......不幸的是,你将不得不重写样式或复制过去,并匹配背景,这样就不会有独立的值为边界元素。边界元素应听取模板父的背景。
查看当前默认模板的最佳方法是使用Blend并选择创建控件模板副本以供编辑的选项。
在internt上也有wpf控件的默认模板,你可以找到ListBoxItem样式,在添加你的编辑之前复制过去。
我不确定Rohit发给你的样式是否是ListBoxItem样式的完整副本。似乎缺少样式设置器。我猜他只是发给你模板。

相关问题