I’ve made two custom classes inheriting from ListView and ListViewItem. I am creating these classes because I want my ListView to have the normal selection capabilities but also want it to have a different color ListViewItem for whichever item is currently “active”. A ListViewItem can be made to be active by double clicking.
My problem is that my property “IsActive” updates to true or false on double click as intended but the color does not change to the trigger set in the style. I’ve added a method named “OnDependencyPropertyChanged” to check whether it’s being property registered but that also is not changing.
I would like to know why this particular solution is not working but am also obviously open to a simpler approach because this does seem a bit unnecessary.
MainWindow.xaml.cs:
namespace TestProject
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<Person> People { get; set; } = new()
{
new Person("Jimbo", "Stevens", 54),
new Person("Hannah", "Johnston", 23),
new Person("Seamus", "O'Halligan", 19)
};
public MainWindow()
{
InitializeComponent();
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
FirstName = firstName;
LastName = lastName;
Age = age;
}
}
}
MainWindow.xaml:
<Window x:Class="TestProject.MainWindow"
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"
xmlns:local="clr-namespace:TestProject"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800"
DataContext="{Binding RelativeSource={RelativeSource self}}">
<Window.Resources>
<Color x:Key="ControlLightColor">#F1F1F1</Color>
<SolidColorBrush x:Key="ControlLightBrush"
Color="{DynamicResource ControlLightColor}" />
<Color x:Key="ControlMediumColor">#999897</Color>
<SolidColorBrush x:Key="ControlMediumBrush"
Color="{DynamicResource ControlMediumColor}" />
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ActiveBackgroundColor">#a6f59f</Color>
<Style x:Key="LayersListViewItemStyle"
TargetType="local:DoubleClickSetListViewItem">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:DoubleClickSetListViewItem">
<Border x:Name="Border"
SnapsToDevicePixels="true"
Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Deactivated" />
<VisualState x:Name="Activated">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{DynamicResource ActiveBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{DynamicResource SelectedBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{DynamicResource SelectedUnfocusedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LayersListViewStyle"
TargetType="local:DoubleClickSetListView">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Foreground"
Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border Name="Border"
BorderThickness="1"
Background="{DynamicResource ControlLightBrush}"
BorderBrush="{DynamicResource ControlMediumBrush}">
<ScrollViewer Margin="1">
<ItemsPresenter />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<local:DoubleClickSetListView ItemsSource="{Binding People}"
Style="{StaticResource LayersListViewStyle}">
<local:DoubleClickSetListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=FirstName}"
Header="First Name" />
<GridViewColumn DisplayMemberBinding="{Binding Path=LastName}"
Header="Last Name" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Age}"
Header="Age" />
</GridView>
</local:DoubleClickSetListView.View>
</local:DoubleClickSetListView>
</Grid>
</Window>
Custom ListView and ListViewItem:
namespace TestProject
{
public class DoubleClickSetListView : ListView
{
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is DoubleClickSetListViewItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return new DoubleClickSetListViewItem();
}
}
public class DoubleClickSetListViewItem : ListViewItem
{
public bool IsActive { get; set; } = false;
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register(
"IsActive",
typeof(bool),
typeof(DoubleClickSetListViewItem),
new PropertyMetadata(default(bool), OnDependencyPropertyChanged));
protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
{
if (IsActive)
{
IsActive = false;
}
else
{
IsActive = true;
}
}
private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
}