我正在使用 DataTemplateSelector 根据枚举值选择 ListBox 项目的 DataTemplates。
public class MenuBarDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
DataTemplate template = null;
var element = container as FrameworkElement;
MenuItemModel model = (MenuItemModel)item;
switch (model.ItemType)
{
case MenuItemType.Home:
template = element.FindResource("MenuItemHome") as DataTemplate;
break;
case MenuItemType.Contacts:
template = element.FindResource("MenuItemContacts") as DataTemplate;
break;
}
return template;
}
}
每个数据模板都有一个用于显示图标的 Path 和一个 TextBlock。它们之间的唯一区别是显示图像的路径根据枚举而不同。
ListBox 的 ItemContainerStyle 有一个触发器来处理 IsMouseOver 影响以更改前景色,当我将鼠标悬停在列表项上时,我可以看到前景色发生变化。顶部的路径样式也有类似的触发器,但只有当鼠标位于路径本身上方时才会改变颜色。
<UserControl.Resources>
<cls:MenuBarDataTemplateSelector x:Key="menuTemplateSelecor"/>
<Style x:Key="pathStyle"
TargetType="{x:Type Path}">
<Setter Property="Height" Value="22" />
<Setter Property="Width" Value="22" />
<Setter Property="Fill" Value="Gray" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Stretch" Value="Fill" />
<Setter Property="Margin" Value="5" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="SteelBlue"/>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="MenuItemHome">
<StackPanel Orientation="Horizontal">
<Path x:Name="path"
Data="{StaticResource homeIcon}"
Style="{StaticResource pathStyle}"/>
<TextBlock Text="{Binding MenuItemName}"
FontSize="14"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="MenuItemContacts">
<StackPanel Orientation="Horizontal">
<Path x:Name="path"
Data="{StaticResource personIcon}"
Style="{StaticResource pathStyle}"/>
<TextBlock Text="{Binding MenuItemName}"
FontSize="14"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0"
ItemsSource="{Binding MenuItems}"
SelectedItem="{Binding SelectedMenuItem}"
ItemTemplateSelector="{StaticResource menuTemplateSelecor}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="3"/>
<Setter Property="Height" Value="40"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Background" Value="Tan"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
这似乎是我在错误的地方有正确的代码。正确的做法是什么?
StackPanel
ListBoxItem
响应悬停事件。使用隐藏代码处理 Path
MouseEnter
和 MouseLeave
事件更改悬停时 Path
的颜色。
<DataTemplate x:Key="MenuItemHome">
<StackPanel Orientation="Horizontal" MouseEnter="OnMouseEnter" MouseLeave="OnMouseLeave">
<Path x:Name="path" Data="{StaticResource homeIcon}" Fill="Gray" Height="22" Width="22" Margin="5"/>
<TextBlock Text="{Binding MenuItemName}" FontSize="14"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="MenuItemContacts">
<StackPanel Orientation="Horizontal" MouseEnter="OnMouseEnter" MouseLeave="OnMouseLeave">
<Path x:Name="path" Data="{StaticResource personIcon}" Fill="Gray" Height="22" Width="22" Margin="5"/>
<TextBlock Text="{Binding MenuItemName}" FontSize="14"/>
</StackPanel>
</DataTemplate>
在你的 C# 中:
private void OnMouseEnter(object sender, MouseEventArgs e)
{
var stackPanel = sender as StackPanel;
var path = stackPanel?.Children.OfType<Path>().FirstOrDefault();
if (path != null)
path.Fill = Brushes.SteelBlue;
}
private void OnMouseLeave(object sender, MouseEventArgs e)
{
var stackPanel = sender as StackPanel;
var path = stackPanel?.Children.OfType<Path>().FirstOrDefault();
if (path != null)
path.Fill = Brushes.Gray;
}