ListBox鼠标在背景颜色

时间:2014-02-23 18:47:24

标签: .net wpf listbox

我遇到的问题是MouseOver触发器为所选行上的背景着色失败 对于任何未选择的行,鼠标悬停后背景变为蓝色 但是所选行没有蓝色背景 单击一行,然后背景蓝色消失。

我也尝试过ListBox.ItemContainerStyle

中的样式
<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;
        }
    }
}

2 个答案:

答案 0 :(得分:11)

如果查看ListBoxItem的默认模板,您会在IsMouseOver触发器之前看到 IsSelected触发器,并且因为dataTriggers是从上到下进行评估的。因此,最后一次触发总是赢得并将ListBoxItem的背景设置为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>

<强>更新

可能我应该多解释一下我上面的断言。

首先,我可以使用Windows 8,Windows 7和Windows 8的默认模板完全不同。对于Windows 8,主题样式是从PresentationFramework.Aero2.dll中选取的,因此defualt模板可能与主题样式不同在PresentationFramework.Aero.dll下找到(用于Windows 7及更早版本)。

我发布了从Aero2.dll获得的默认模板。正如您在默认模板中看到的那样,它不会使用HighlightBrushKey,因此您在覆盖HighlightBrushKey的位置发布的问题在首先不起作用。 (这就是我不喜欢覆盖系统画笔的原因,因为它可能不适用于使用其他主题风格的模板)。

根据Dev的回答

  

样式触发器优先于模板触发器,所以它   如果模板触发器位于第一个或最后一个位置,则无关紧要   列表。

我同意Style触发器优先于模板触发器。但是,我在回答中提到的是当你没有使用任何Style触发器并只是在模板中提供值时的情况。默认情况下,模板MouseOverTrigger位于顶部,SelectedItem位于此下方。所以,在这种情况下,订单确实很重要。您可以通过向上移动触发器并删除所有Style触发器来验证您的自我。

关于

  

我不确定Rohit发布给你的风格是否完整   ListBoxItem样式。似乎缺少样式制定者。他只是   我猜你发布了模板。

我发布了Aero2.dll下找到的ListBoxItem的完整模板,显然可能因主题样式而有所不同。

我使用XamlWriter.Save(listBoxItem.Template, xmlwrite);

获得了样式

答案 1 :(得分:2)

你有一个迭代问题。我在编写主题时也曾有过这段时间。

问题不在于触发器的顺序,或者触发器位于底部而不是触发器。

样式触发器优先于模板触发器,因此如果模板触发器位于列表的第一个或最后一个位置,则无关紧要。

你遇到的问题在wpf中非常罕见。在你的情况下,简单地忽略了implict样式的触发器,因为border的背景与模板化父级的背景不匹配。

在您的情况下,当selected属性为true时,microsoft将在内部调用触发器。触发器内部直接在border元素上设置背景颜色,名称为“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并选择创建contro模板副本以供编辑的选项。

在internt的某处还有wpf控件的默认模板。您可以在向其添加编辑之前找到ListBoxItem样式并复制它。

我不确定Rohit发布给你的样式是否是ListBoxItem样式的完整副本。似乎缺少样式制定者。他只是贴了我猜的模板。