我将 WPF 与 ListView 一起使用(我可以使用 ListBox,问题仍然相同)。
我的 ListViewItem 具有自定义样式,模型具有 DataTemplate。我想使用 DataTemplate 上的 DataTrigger 更改 ListViewItem 的背景颜色。
有没有办法在 DataTemplate 上创建 DataTrigger,并让它以 ListViewItem 的 AncestorType 为目标来设置其背景?
下面是我的代码的简化版本。
这是我的模型(
ObservableObject
实现了INotifyPropertyChanged
)。
对于上下文,它是读取的 RFID 标签,并且 SeenRecently
布尔值将指示该标签在最后一秒内被看到。当此属性为 true 时,我希望将 ListViewItem 背景颜色设置为“绿色”。
public class TagEntry : ObservableObject
{
private string? serialNumber;
public string? SerialNumber
{
get { return serialNumber; }
set { SetProperty(ref serialNumber, value); }
}
private string? tagType;
public string? TagType
{
get { return tagType; }
set { SetProperty(ref tagType, value); }
}
private bool seenRecently;
public bool SeenRecently
{
get { return seenRecently; }
set { SetProperty(ref seenRecently, value); }
}
}
这是我的
ListViewItem
风格(为了简洁删除了一些 Setter)。它有 2 个触发器,这是有意义的,因为 IsSelected
和 IsMouseOver
是在 ListViewItem
上找到的属性。
第三个触发器,用于我的数据模型上的
SeenRecently
属性来设置背景。
这确实有效,但现在我将此样式与我的数据模型耦合,如果我想在其他数据模型中重新使用此样式怎么办?
<Style x:Key="myItemContainerStyle"
TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Beige"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="MediumPurple"/>
</Trigger>
<!-- This here works, but i'm now coupling my ListViewItem Style, with my Model -->
<DataTrigger Binding="{Binding SeenRecently}" Value="True">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
这是我的 DataTemplate,这是放置 DataTrigger 的有意义的地方,但我不知道如何/是否可以定位
ListViewItem
类型的祖先来从这里设置其背景。
<DataTemplate x:Key="TagTypeDataTemplate" DataType="model:TagEntry">
<Grid Grid.Column="1" Margin="4">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding SerialNumber}" FontSize="24" FontWeight="SemiBold"/>
<TextBlock Grid.Row="1" Text="{Binding TagType}" FontSize="18"/>
</Grid>
</DataTemplate>
这是示例图像。鼠标悬停时为紫色背景,
SeenRecently
项目为绿色。
也许我的想法是错误的,也许我应该有一个专门针对我的数据模型的特殊<Style TargetType="ListViewItem">
?
经过一番尝试后,我认为对我来说最好的选择是为我的 ListViewItem 创建一个基本样式。然后为我的模型创建一个子样式,以触发更改。
我可以轻松地重复使用基本样式,并为我想要触发更改的任何其他模型创建一个新的小样式。
<Style x:Key="TagEntryListViewContainerStyle"
TargetType="ListViewItem"
BasedOn="{StaticResource BaseListViewContainerStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(model:TagEntry.SeenRecently)}" Value="True">
<Setter Property="Background" Value="LightGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>