如何移除WPF ListViewItem样式中出现的IsMouseOver渐变效果?

10
在以下Window中,我为IsMouseOver定义了一个触发器。背景颜色被正确地改变,但它有一个渐变效果。请参见下面的图片。如何摆脱这种效果?enter image description here 只有Theme.DataGrid.Row.Background.Hover从单独的样式文件移动到以下代码片段中。
<Window x:Class="MyCompany.Application.Shared.UI.Dialogs.SomeWindow
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Background="#FFF3F3F7">
    <Window.Resources>
        <SolidColorBrush x:Key="Theme.DataGrid.Row.BorderBrush" Color="#FFF3F3F7" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Background" Color="White" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Hover" Color="#FFAEAEB6" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Active" Color="#FF0D6AA8" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Background.HoverSelected" Color="#FF009AD9" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Disabled" Color="#FFAEAEB6" options:Freeze="True" />
        <SolidColorBrush x:Key="Theme.DataGrid.Row.Foreground.Selected" Color="White" options:Freeze="True" />

        <Style x:Key="GridView.ColumnHeader.Gripper.Style" TargetType="{x:Type Thumb}">
            <Setter Property="Width" Value="8" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Cursor" Value="SizeWE" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type GridViewColumnHeader}" >
            <EventSetter Event="FrameworkElement.Loaded" Handler="GridViewColumnHeader_Loaded"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Background" Value="{StaticResource Theme.DataGrid.ColumnHeader.Background}"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="1" />
                            </Grid.ColumnDefinitions>
                            <Border Grid.Column="0"  x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                                <ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                            </Border>
                            <Thumb Grid.Column="1" x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Style="{DynamicResource Theme.DataGrid.ColumnHeader.Gripper.Style}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type ListView}" >
            <Setter Property="BorderThickness" Value="{DynamicResource Theme.DataGrid.BorderThickness}"/>
            <Setter Property="Background" Value="{StaticResource Theme.TreeView.Background}"/>
        </Style>

        <Style TargetType="{x:Type ListViewItem}" >
            <Setter Property="Background" Value="White" />
            <Setter Property="Foreground" Value="{DynamicResource Theme.DataGrid.Row.Foreground}" />
            <Setter Property="VerticalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="Padding" Value="{DynamicResource Theme.DataGrid.Cell.Padding}"/>
            <Setter Property="Margin" Value="1"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Hover}" />
                </Trigger>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Active}" 
                    <Setter Property="Foreground" Value="{DynamicResource Theme.DataGrid.Row.Background.Selected}" />
                </Trigger>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Disabled}" />
                </Trigger>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="True" />
                        <Condition Property="IsSelected" Value="True" />
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.HoverSelected}" />
                </MultiTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <StackPanel>
        <CheckBox Content="IsGrouped"  IsChecked="{Binding IsGrouped}"/>
        <ListView Margin="10" ItemsSource="{Binding Users}">    
            <ListView.View>
                <GridView AllowsColumnReorder="False">
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age"  DisplayMemberBinding="{Binding Age}" />
                    <GridViewColumn Header="Mail"  DisplayMemberBinding="{Binding Mail}" />
                    <GridViewColumn Header="Group"  DisplayMemberBinding="{Binding Group}" />
        </ListView>
    </StackPanel>
</Window>

ViewModel(请注意,这里使用的是我们自己的ViewModel类,它会触发PropertyChanged事件)

namespace MyCompany.Application.Shared.UI.Dialogs
{
    public class User
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public string Mail { get; set; }

        public string Group { get; set; }
    }

    public class SomeWindowViewModel : ViewModel
    {
        List<User> items = new List<User>();

        IEnumerable<User> GetUsers()
        {
            foreach (var item in items)
            {
                yield return item;
            }
        }
        public ICollectionView Users { get; }

        private bool _isGrouped = false;
        public bool IsGrouped
        {
            get { return _isGrouped; }
            set
            {
                _isGrouped = value;
                if (value)
                {
                    Users.GroupDescriptions.Add(new PropertyGroupDescription("Group"));
                }
                else
                {
                    Users.GroupDescriptions.Clear();
                }
            }
        }

        public SomeWindowViewModel()
        {
            items.Add(new User() { Name = "John Doe", Age = 42, Mail = "john@doe-family.com", Group = "OneGroup1" });
            items.Add(new User() { Name = "Jane Doe", Age = 39, Mail = "jane@doe-family.com", Group = "OneGroup1" });
            items.Add(new User() { Name = "Sammy Doe", Age = 7, Mail = "sammy.doe@gmail.com", Group = "TwoGroup2" });
            items.Add(new User() { Name = "Pentti Doe", Age = 7, Mail = "pena.doe@gmail.com", Group = "TwoGroup2" });
            Users = CollectionViewSource.GetDefaultView(GetUsers());
        }
    }
}

2
你正在使用的 ListViewItem 样式没有指定 ControlTemplate,因此,你看到的 渐变效果 来自默认效果。所以,如果你想摆脱它,你将不得不定义自己的样式/模板。如果你做得好...:O),你会得到你想要的 - jsanalytics
1
感谢 @jsanalytics! - char m
1
顺便说一句,2:在所谓的重复问题中没有一个答案是正确的。如果您应用了被接受的、最高票的答案中建议的样式,这就是您会得到的结果。请注意,列数据已经消失了...所以,这是一个严重的“重复失败”... :O)我投票要求重新打开此问题。 - jsanalytics
1
我会在周末回来处理这个问题。如果重新开放的话,我希望能够发布可行的解决方案。我匆忙检查了所谓的重复问题,但我认为我可以不用它来解决。 - char m
1
@charm,能否请您提供所有必需的笔刷和一个样本数据源? - Thomas Flinkow
显示剩余9条评论
1个回答

9

我在给定的代码示例中遇到了一些问题,比如缺少资源或无法解决的其他 options:Freeze="true",因此我的解决方案可能看起来有点不同,但我认为它可以达到你想要的效果:它去掉了渐变效果。


问题在于默认的 ListViewItem 模板具有触发器,可以更改背景(正如您也发现的那样),而解决方法是使用简化的没有任何触发器的 ControlTemplate

这个简化模板的示例是有效的,您可以将它放在您的 {x:Type ListViewItem} 中,以获得类似下面图片展示的外观。

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ListViewItem}">
            <Border Padding="{TemplateBinding Padding}"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="true">
                <GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

使用该模板,如果您首先选择"Sammy Doe 7",然后悬停在"Jane Doe 39"上方,它将如下所示:

enter image description here

如果您选择(例如,单击)"Jane Doe 39",则它将如下所示:

enter image description here


我不完全确定您的意思是什么,

正如jsanalytics所指出的那样,控件模板导致行成为类名而不是数据

但据我所知,上面的代码不应导致该行为。如果确实有这种情况,请告诉我,我会找到另一个解决方案。

1
我已经尝试了一周,使用GridViewRowPresenter,但是我只得到了类名。无论如何,我接受这个结果,并在晚上有时间再尝试一下(以防它会破坏其他东西),并授予悬赏。 - char m
1
使用这个:xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" - jsanalytics
1
@jsanalytics 谢谢你提到命名空间,它看起来很有趣,我会去了解一下。 - Thomas Flinkow
2
此外,您不需要妥协于一个半成品的“简化”模板。很快你会回到起点:没有完全控制你的东西。在这种情况下,触发器应该在控制模板中,而不是样式中。 - jsanalytics
1
@jsanalytics,我不确定我理解你的意思。当然,这个模板并不完整,但是我所说的“简化”是指“没有OP不需要的触发器”。当然,他们可以添加所有他们想要的触发器、属性等。 - Thomas Flinkow
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接