我创建了两个继承自 ListView 和 ListViewItem 的自定义类。我创建这些类是因为我希望我的 ListView 具有正常的选择功能,但也希望它对于当前处于“活动”状态的项目具有不同颜色的 ListViewItem。双击可以激活 ListViewItem。
我的问题是我的属性“IsActive”在双击时按预期更新为 true 或 false,但颜色不会更改为样式中设置的触发器。我添加了一个名为“OnDependencyPropertyChanged”的方法来检查它是否正在注册属性,但这也没有改变。
我想知道为什么这个特定的解决方案不起作用,但我显然也愿意采用更简单的方法,因为这似乎有点不必要。
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>
自定义ListView和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)
{
}
}
}
正确的创建方式是这样的
DependencyProperty
public bool IsActive
{
get { return (bool)GetValue(IsActiveProperty); }
set { SetValue(IsActiveProperty, value); }
}
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register("IsActive", typeof(bool), typeof(ownerclass), new PropertyMetadata(default(bool), OnDependencyPropertyChanged)));
如您所见,
IsActive
属性也不用于存储值,而只是用于访问 DependencyProperty GetValue
和 SetValue
。
作为提示,Visual Studio 中有一个用于创建 DependencyProperties 的片段,即
propdp
。