WPF ListViewItem - 切换可聚焦和 IsMouseOver 背景值

WPF ListViewItem - Switch focusable and IsMouseOver background values

我正在尝试显示具有不同对象类型的列表(在示例中为狗和猫)。类型应该在视觉上有所不同(在 MainWindow.xaml 中 DataTemplate 中使用红色和蓝色字体实现的示例中)。

此外,我希望猫既不能被选中,也不能在 IsMouseOver 触发器中获得彩色背景。但是,我在后者方面没有成功。我在 MainWindow.xaml.

中留下了一些我的尝试作为评论

MainWindow.xaml

<Window.Resources>
    <local:AnimalToFocusConverter x:Key="AnimalToFocusConverter" />
    <local:AnimalToBackgroundColorConverter x:Key="AnimalToBackgroundColorConverter" />

    <DataTemplate DataType="{x:Type local:Dog}">
        <TextBlock Text="{Binding Path=Name}" Foreground="Red" />
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:Cat}">
        <TextBlock Text="{Binding Path=Name}" Foreground="Blue" />
    </DataTemplate>
</Window.Resources>
<Grid>
    <ListView ItemsSource="{Binding AnimalCollection}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Background" Value="Transparent" />
                <!--<Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListViewItem}">
                            <Grid Background="Transparent">
                                <ContentPresenter />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{Binding Converter={StaticResource AnimalToBackgroundColorConverter}}" />
                    </Trigger>
                </Style.Triggers>-->
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>

Animals.cs

public class Animals
{
    public ObservableCollection<IAnimal> AnimalCollection { get; set; } = new ObservableCollection<IAnimal>();

    public Animals()
    {
        AnimalCollection.Add(new Dog());
        AnimalCollection.Add(new Dog());
        AnimalCollection.Add(new Cat());
        AnimalCollection.Add(new Dog());
        AnimalCollection.Add(new Cat());
    }
}

IAnimal.cs

public interface IAnimal
{
}

Dog.cs / Cat.cs

public class Dog : ObservableObject, IAnimal
{
    private static int counter = 0;
    public string Name { get; set; }

    public Dog()
    {
        Name = $"Dog{++counter}";
    }
}

Converter.cs

[ValueConversion(typeof(IAnimal), typeof(bool))]
public class AnimalToFocusConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value switch
        {
            Dog => true,
            Cat => false,
            _ => false,
        };
    }

// ...

[ValueConversion(typeof(IAnimal), typeof(SolidColorBrush))]
public class AnimalToBackgroundColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value switch
        {
            Dog => new SolidColorBrush(Colors.LightBlue),
            Cat => new SolidColorBrush(Colors.Transparent),
            _ => new SolidColorBrush(Colors.LightBlue),
        };
    }

您可以将 Cat 对象的 ListViewItem 容器的 IsHitTestVisible 属性 设置为 false:

<ListView ItemsSource="{Binding AnimalCollection}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="IsHitTestVisible"
                    Value="{Binding Converter={StaticResource AnimalToFocusConverter}}" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>