UWP 未聚焦的 VisualState 覆盖了 ListViewItem 上的选定 VisualState

UWP unfocused VisualState overriding selected VisualState on ListViewItem

我有一个在其 ItemContainerStyle 上使用自定义样式的 ListView 属性。

问题是,当我使用键盘浏览列表中的项目时,如果我浏览到当前选定的项目,它会获得焦点样式(这很好),但是当我浏览时远离该项目,它开始使用未聚焦的样式而不是选定的样式。

例如,假设在 ListView 中选择了 5 项中的第 3 项。在列表获得焦点之前看起来像这样,这是正确的:

然后我使用键盘导航到列表,该列表将“聚焦”样式应用于所选项目,这很好...

但是当我按下向下箭头键向下导航时,突然间第三项看起来不再是“选中的”。看起来这只是一个普通的未选中项目:

发生这种情况是因为“未聚焦”状态覆盖了第三项的“选定”视觉状态,但我希望它是相反的。

注意:我在 ListView 上有 SingleSelectionFollowsFocus="False"。

如果我删除“未选择”状态,然后将焦点从第三个项目移开,我导航的任何项目看起来就像它当前处于聚焦状态...如果我能弄清楚为什么会这样,然后我可以安全地删除“未选择”状态,它会正常工作。

如何在取消聚焦后保留所选项目的“选定”视觉状态?

这是我的代码:

XAML:

<ListView x:Name="ThingieListView"
                                  ItemsSource="{x:Bind viewModel.ThingieDataList}"
                                  SingleSelectionFollowsFocus="False"
                                  SelectionMode="Single"
                                  IsItemClickEnabled="True"
                                  XYFocusRight="{x:Bind LocationListView}"
                                  Margin="8"
                                  Width="256"
                                  IsTabStop="True"
                                  TabIndex="0"
                                  LostFocus="ThingieListView_LostFocus"
                                  GotFocus="ThingieListView_GotFocus"
                                  ItemClick="ThingieListView_OnItemClick"
                                  ItemContainerStyle="{StaticResource SelectThingieItemStyle}">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ListViewItem Content="{Binding DisplayValue}"  />
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView> 

自定义样式:

<Style x:Key="SelectThingieItemStyle" TargetType="ListViewItem">
        <Setter Property="FontFamily" Value="{StaticResource Res-FontFamily}"/>
        <Setter Property="FontSize" Value="{StaticResource FontSizeText2}"/>
        <Setter Property="Background" Value="{ThemeResource ListViewItemBackground}"/>
        <Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}"/>
        <Setter Property="TabNavigation" Value="Local"/>
        <Setter Property="IsHoldingEnabled" Value="True"/>
        <Setter Property="Padding" Value="0,0,0,0"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
        <Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>
        <Setter Property="AllowDrop" Value="False"/>
        <Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
        <Setter Property="FocusVisualMargin" Value="0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListViewItem">
                    <ListViewItemPresenter x:Name="Root"
                                           CheckBrush="{ThemeResource ListViewItemCheckBrush}"
                                           ContentMargin="15"
                                           Height="63"
                                           Margin="0 0 0 1"
                                           CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
                                           ContentTransitions="{TemplateBinding ContentTransitions}"
                                           CheckMode="{ThemeResource ListViewItemCheckMode}"
                                           DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
                                           DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
                                           DragBackground="{ThemeResource ListViewItemDragBackground}"
                                           DragForeground="{ThemeResource ListViewItemDragForeground}"
                                           FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
                                           FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
                                           FocusVisualPrimaryThickness="0"
                                           FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
                                           HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                           Control.IsTemplateFocusTarget="True"
                                           PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
                                           PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
                                           PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
                                           PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
                                           RevealBorderThickness="{ThemeResource ListViewItemRevealBorderThemeThickness}"
                                           ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
                                           RevealBorderBrush="{ThemeResource ListViewItemRevealBorderBrush}"
                                           RevealBackground="{ThemeResource ListViewItemRevealBackground}"
                                           SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
                                           SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}"
                                           SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
                                           SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
                                           SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
                                           VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <VisualState.Setters>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_2}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Gray_1}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="0"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Selected">
                                    <VisualState.Setters>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Black}"/>
                                        <Setter Target="Root.FontWeight" Value="Bold"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="0"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_4}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_2}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="3"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="PointerOverSelected">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_4}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="3"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="PointerOverPressed">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_2}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="3"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-Black}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBorderThickness" Value="3"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                        <Setter Target="Root.FontWeight" Value="Bold"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="PressedSelected">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBorderThickness" Value="3"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                        <Setter Target="Root.FontWeight" Value="Bold"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusedStates">
                                <VisualState x:Name="Focused">
                                    <VisualState.Setters>
                                        <Setter Target="Root.FontWeight" Value="Bold"/>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-Black}"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="0 0 20 0"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Orange}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Unfocused">
                                    <VisualState.Setters>
                                        <Setter Target="Root.Foreground" Value="{StaticResource Res-White}"/>
                                        <Setter Target="Root.RevealBackground" Value="{StaticResource Res-Gray_2}"/>
                                        <Setter Target="Root.RevealBorderBrush" Value="{StaticResource Res-Gray_1}"/>
                                        <Setter Target="Root.RevealBorderThickness" Value="0 1 0 1"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="DisabledStates">
                                <VisualState x:Name="Enabled"/>
                                <VisualState x:Name="Disabled">
                                    <VisualState.Setters>
                                        <Setter Target="Root.RevealBorderThickness" Value="0"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </ListViewItemPresenter>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        
    </Style> 

How can I retain the "selected" visual state of the selected item after unfocusing it?

正如你所说,“未聚焦”状态会覆盖“选中”状态,如果你想显示“选中”状态,你可以尝试在选中项丢失时手动触发“选中”视觉状态关注 VesselListView_LostFocus 事件。首先判断失去焦点的项目是否被选中,如果是,则可以触发“选中”状态。例如:

private void VesselListView_LostFocus(object sender, RoutedEventArgs e)
{
    ListViewItem litem = e.OriginalSource as ListViewItem;
    if (litem != null && litem.IsSelected == true)
    {
        VisualStateManager.GoToState(litem, "Selected", false);
    }
}