10

In the following Window I define a trigger for IsMouseOver. The background color is changed correctly, but it has an gradient effect. See the pic below. How to get rid of the effect? enter image description here

Only Theme.DataGrid.Row.Background.Hover is moved from separate style file to code excerpt below.

<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 (note that this uses our own ViewModel-class that i.e raises PropertyChanged events)

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());
        }
    }
}
Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65
char m
  • 7,840
  • 14
  • 68
  • 117
  • 2
    The `ListViewItem` style you're using does NOT specify a `ControlTemplate`, and therefore, the _gradient effect_ you're seeing comes from the default one. So, if you want to get rid of that, you will have to define your own style/template. And if you play your cards right...:O), [you will get what you want](https://imgur.com/pIjFVy9). – jsanalytics Mar 10 '18 at 14:03
  • 1
    thanks @jsanalytics! – char m Mar 12 '18 at 08:54
  • You're very welcome ! – jsanalytics Mar 12 '18 at 11:49
  • BTW, please post your working solution ! – jsanalytics Mar 12 '18 at 13:25
  • 1
    BTW 2 : none of the answers in the supposed duplicate does it. If you apply the suggested style from the accepted, most up voted answer, [this is what you get](https://imgur.com/CB4zvSV). Notice that column data is gone.... so, major **duplicate FAIL**... :O) I'm voting to **reopen** this question. – jsanalytics Mar 12 '18 at 16:21
  • 1
    i'm getting back to this on weekend. i'll hopefully post the working solution (if reopened?). i checked the supposed duplicate maybe too hastily but i think i can manage without it. – char m Mar 16 '18 at 07:53
  • Besides voting for reopen you can also **flag** it for moderator attention. I actually did it, but it's been _pending_ . – jsanalytics Mar 16 '18 at 10:11
  • @charm re-opened, please do share your solution – Flexo Mar 19 '18 at 08:44
  • @Flexo: i really wish i had solution. as jsanalytics points out control template results in rows to be class names and not the data. there's now bounty for this. – char m Mar 19 '18 at 08:51
  • 1
    @charm can you please provide all the required brushes and a sample data source? – Thomas Flinkow Mar 19 '18 at 10:14
  • @ThomasFlinkow: I edited and added hopefully everything needed – char m Mar 19 '18 at 10:47
  • @charm not quite yet -- the brushes `Theme.TreeView.Background`, `Theme.DataGrid.ColumnHeader.Background`, `Theme.DataGrid.ColumnHeader.Foreground`, the colors `Color.Trimble_Blue` and `Color.Gray_4` are undefined as well as the `Theme.DataGrid.ColumnHeader.FontWeight`. But I will try to find a solution regardless of the exact values of those. – Thomas Flinkow Mar 19 '18 at 11:16
  • sorry about that. i edit again. – char m Mar 19 '18 at 11:21
  • 1
    Suggestion: create a `Duplicate Buster` badge...:O) – jsanalytics Mar 19 '18 at 13:13

1 Answers1

9

I had some issues with the given code sample, e.g. missing resources or additional options:Freeze="true" which could not be resolved, therefore my solution may look a little different, but I think it does what you want: it removes the gradient effect.


The issue is that the default ListViewItem template has triggers which change the background (as you have found out as well) and the way around is to use a simplified ControlTemplate without any triggers.

This example of a simplified template works and you can put it in your {x:Type ListViewItem} to get a look like shown in the pictures below.

<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>

Using that template, this is what it will look like if you first selected "Sammy Doe 7" and then hover over "Jane Doe 39",

enter image description here

and this is how it looks when you select (e.g. click on) "Jane Doe 39":

enter image description here


I'm not entirely sure what you mean with

as jsanalytics points out control template results in rows to be class names and not the data

but as far as I understand it, above code should not lead to that behavior. If it does, let me know and I will find another solution.

Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65
  • thanks! so this was a duplicate after all, but not duplicate of the one that is marked as duplicate of. – char m Mar 19 '18 at 12:13
  • @charm kind of I think ;-) but it was tricky, because using a `ContentPresenter` instead of the `GridViewRowPresenter` lead to the binding error you described. – Thomas Flinkow Mar 19 '18 at 12:15
  • 1
    i tried already a week ago with GridViewRowPresenter and all i got was class names. anyway i accept this and grant the bounty in the evening when i have time to try it a bit more (in case it breaks something else). – char m Mar 19 '18 at 12:29
  • @charm thank you very much. I'm glad I could help, and if it does break anything, I will gladly try to help. I still have the test project I created for this, so it shouldn't be overly difficult. – Thomas Flinkow Mar 19 '18 at 12:30
  • 1
    Use this: `xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"`. – jsanalytics Mar 19 '18 at 12:48
  • 1
    @jsanalytics thank you for mentioning the namespace, it looks interesting and I will look into it. – Thomas Flinkow Mar 19 '18 at 12:49
  • 2
    Also, you don't need to cave-in to a half-baked, "simplified" template. Soon you'll be where you started: without having full control of your stuff. In this case, triggers should be in the control template, not the style. – jsanalytics Mar 19 '18 at 12:53
  • 1
    @jsanalytics I'm not sure I get your point. Sure, the template is not complete, but I meant "simplified" as in "without the triggers the OP does not need". Of course they can add all the triggers, properties etc. they want. – Thomas Flinkow Mar 19 '18 at 13:01