Chip 的 ListBox 和 DataTrigger 问题

Problem with ListBox and DataTrigger for Chip

我对 ListBoxItemDataTrigger 有疑问。 当用鼠标单击芯片项目时,我想更改 Chip 项目的 Background 颜色。

我认为问题出在这行代码

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem},Path=IsSelected}"
             Value="True">
    <Setter Property="IconBackground"
            Value="#1b5eb2" />
    <Setter Property="Opacity"
            Value="1"></Setter>
</DataTrigger>

运行 我的代码我得到了一个信号类别列表(如下面的屏幕截图所示):

但是,当我用鼠标点击它们时,圆圈的颜色没有改变。

它应该像这样工作(点击时):

我尝试了一些东西并检查了很多关于 DataTrigger 的主题,但我似乎无法弄清楚。

我的.xaml 观点

<ListBox Name="SignalCategories"
         ItemsSource="{Binding DefinedSignalCategories}"
         SelectionMode="Single"
         HorizontalAlignment="Center"
         VerticalAlignment="Top"
         BorderThickness="0">

    <!--changing default ListBoxItem to hide selection highlight-->
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <ContentPresenter />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>

    <!--changing default orientation-->
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    <ListBox.ItemTemplate>
        <DataTemplate>
            <!--custom view-->
            <materialDesign:Chip Content="{Binding Name}"
                                 Margin="5"
                                 IconForeground="{DynamicResource PrimaryHueDarkForegroundBrush}">
                <materialDesign:Chip.Style>
                    <Style TargetType="{x:Type materialDesign:Chip}">
                        <Setter Property="Opacity"
                                Value="0.85" />
                        <Setter Property="IconBackground"
                                Value="Gray"></Setter>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver"
                                     Value="True">
                                <Setter Property="Opacity"
                                        Value="1" />
                                <Setter Property="IconBackground"
                                        Value="#1b5eb2">
                                </Setter>
                            </Trigger>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem},Path=IsSelected}"
                                         Value="True">
                                <Setter Property="IconBackground"
                                        Value="#1b5eb2" />
                                <Setter Property="Opacity"
                                        Value="1"></Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </materialDesign:Chip.Style>
                <materialDesign:Chip.Icon>
                    <materialDesign:PackIcon Kind="{Binding IconName}" />
                </materialDesign:Chip.Icon>
            </materialDesign:Chip>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我发现问题出在 materialDesign:Chip 上。 我在没有使用 materialDesign 的情况下重做了它,现在它可以正常工作了。

工作代码:

<ListBox.ItemTemplate>
<DataTemplate>
    <!--custom view-->
    <Grid Width="auto"
          Height="30"
          x:Name="grid1"
          Margin="10">
        <Border BorderBrush="Transparent"
                HorizontalAlignment="Left"
                Background="#939393"
                Panel.ZIndex="1000"
                BorderThickness="0"
                CornerRadius="30"
                Width="30"
                Height="30"
                x:Name="BorderCircle">
            <materialDesign:PackIcon Kind="{Binding IconName}"
                                     Margin="5"
                                     VerticalAlignment="Center"
                                     HorizontalAlignment="Center"
                                     Foreground="White" />
        </Border>
        <Border Background="#efefef"
                BorderThickness="0"
                CornerRadius="15"
                HorizontalAlignment="Right"
                Margin="10 0 0 0">

            <TextBlock Text="{Binding Name}"
                       HorizontalAlignment="Right"
                       VerticalAlignment="Center"
                       Margin="25 0 10 0" />
        </Border>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                     Value="True">
            <Setter TargetName="BorderCircle"
                    Property="Background"
                    Value="#1b5eb2" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

输出:

这不起作用的原因是您误用了 Chip 控件。是一个类型derived from ButtonBase, which means it is basically a button. It handles mouse click events, which sets the e.Handled flag of the corresponding routed event arguments to true. See The Concept of Handled供参考

The value of Handled affects how a routed event is reported or processed as it travels further along the route. If Handled is true in the event data for a routed event, then handlers that listen for that routed event on other elements are generally no longer invoked for that particular event instance.

因此,Chip 上的点击被 ListBoxItem 忽略,因此未被选中。您当然可以使用在 code-behind 中使用 handledEventsToo 注册点击处理程序的解决方法,如文章中所述,然后在可视化树中搜索 ListBoxItem 并设置 IsSelected true,但我不推荐它,因为首先使用它是错误的控件。由于 Chip 是一个按钮,因此它具有 Mouse OverPressed 的视觉状态以及您可以执行的其他状态和大量标记不需要也不必为了 使按钮表现得像不是按钮一样进行覆盖 。这没有意义。

你可以做的是 copy the essentials of the default style for Chip 并从中制作 DataTemplate 或自定义控件。以下数据模板应该适合您。

<ListBox.ItemTemplate>
   <DataTemplate>
      <Grid>
         <Grid.Resources>
            <materialDesign:NullableToVisibilityConverter x:Key="NullableToVisibilityConverter" />
            <materialDesign:PackIcon x:Key="Icon"
                                     Kind="{Binding IconName}" />
         </Grid.Resources>
         <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
         </Grid.ColumnDefinitions>
         <Border CornerRadius="16"
                 Background="{DynamicResource MaterialDesignChipBackground}"
                 Grid.ColumnSpan="3" />
         <ContentControl Grid.Column="0"
                         Content="{StaticResource Icon}"
                         Background="{DynamicResource PrimaryHueMidBrush}"
                         FontSize="17"
                         FontWeight="Regular"
                         IsTabStop="False"
                         Visibility="{Binding Source={StaticResource Icon}, Converter={StaticResource NullableToVisibilityConverter}}"
                         VerticalAlignment="Center"
                         VerticalContentAlignment="Center"
                         HorizontalContentAlignment="Center"
                         Height="32"
                         Width="32">
            <ContentControl.Style>
               <Style TargetType="{x:Type ContentControl}">
                  <Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidForegroundBrush}"></Setter>
                  <Style.Triggers>
                     <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
                                  Value="True">
                        <Setter Property="Foreground"
                                Value="White" />
                     </DataTrigger>
                     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem},Path=IsSelected}"
                                  Value="True">
                        <Setter Property="Foreground"
                                Value="White" />
                     </DataTrigger>
                  </Style.Triggers>
               </Style>
            </ContentControl.Style>
            <ContentControl.Clip>
               <EllipseGeometry RadiusX="16"
                                RadiusY="16"
                                Center="16,16" />
            </ContentControl.Clip>
            <ContentControl.Template>
               <ControlTemplate TargetType="ContentControl">
                  <Border x:Name="ChipBackgroundBorder"
                          Background="{DynamicResource MaterialDesignChipBackground}">
                     <ContentPresenter Content="{TemplateBinding Content}"
                                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                  </Border>
                  <ControlTemplate.Triggers>
                     <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
                                  Value="True">
                        <Setter TargetName="ChipBackgroundBorder"
                                Property="Opacity"
                                Value="1" />
                        <Setter TargetName="ChipBackgroundBorder"
                                Property="Background"
                                Value="#1b5eb2" />
                     </DataTrigger>
                     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem},Path=IsSelected}"
                                  Value="True">
                        <Setter TargetName="ChipBackgroundBorder"
                                Property="Background"
                                Value="#1b5eb2" />
                        <Setter TargetName="ChipBackgroundBorder"
                                Property="Opacity"
                                Value="1" />
                     </DataTrigger>
                  </ControlTemplate.Triggers>
               </ControlTemplate>
            </ContentControl.Template>
         </ContentControl>
         <ContentControl Content="{Binding Name}"
                         x:Name="TextBlock"
                         IsTabStop="False"
                         VerticalAlignment="Center"
                         Margin="8 0 12 0"
                         Grid.Column="1" />
      </Grid>
   </DataTemplate>
</ListBox.ItemTemplate>

此模板与您 use-case 的 Chip 模板几乎相同,但是,您可能需要考虑创建自己的模板并大幅简化它以仅满足您的要求。