UWP - Flyout中的WinRT xaml工具包TreeView,在弹出窗口关闭后更改选择

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UWP - Flyout中的WinRT xaml工具包TreeView,在弹出窗口关闭后更改选择相关的知识,希望对你有一定的参考价值。

我目前正在尝试使用WinRT xaml ToolKit TreeView组件,因为UWP本身不支持它。

TreeView位于Flyout按钮内。当我按下按钮时我想要Flyout出现,所以我可以从树中选择一个项目。我将一个命令从ViewModel绑定到SelectedItemChanged事件:

<Button
   x:Name="btnFilter"
   HorizontalAlignment="Right"
   Command="{Binding OpenFiltersCommand}"
   Style="{StaticResource SecondaryMenuButtonStyle}">
   <StackPanel Orientation="Horizontal">
     <Image
       Width="28"
       Margin="0,0,4,0"
       Source="{StaticResource FilterIcon}" />
     <TextBlock x:Uid="Filter" Style="{StaticResource GrayTextBlockStyle}" />
   </StackPanel>
   <FlyoutBase.AttachedFlyout>
     <controls1:CustomFlyout IsOpen="{Binding IsFiltersOpen, Mode=TwoWay}" Parent="{Binding ElementName=btnFilter}">
        <controls2:TreeView
          ItemContainerStyle="{StaticResource DefaultTreeViewItem}"
          ItemTemplate="{StaticResource TreeViewItemTemplate}"
          ItemsSource="{Binding BuildingTree}"
          Style="{StaticResource DefaultTreeViewStyle}">
            <i:Interaction.Behaviors>
              <core:EventTriggerBehavior EventName="SelectedItemChanged">
                <core:InvokeCommandAction Command="{Binding ChangeRoomCommand}" />
              </core:EventTriggerBehavior>
            </i:Interaction.Behaviors>
         </controls2:TreeView>
      </controls1:CustomFlyout>
   </FlyoutBase.AttachedFlyout>
</Button>

从TreeView中选择一个项目后,SelectedItemChanged事件将按原样触发,但之后我关闭了Flyout并且事件再次触发。第二次它通常会在当前的父元素之后触发新的选定元素。所以例如,如果我有这个结构:

1
--1.0
--1.1
--1.2
2
--2.0
--2.1

因此,如果我选择--1.1,则第一个SelectedItemChanged将使用--1.1元素触发,然后它将以2作为新选择的项目触发。

注意:我正在使用可以从ViewModel关闭的CustomFlyout组件,但我也使用常规Flyout对此进行了测试,并且在通过单击外部关闭Flyout后发生同样的事情。

更新:我已经下载了WinRT代码并开始在本地调试TreeView组件。在TreeViewItem.cs中,我在这个函数中找到了问题的根源:

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        // Since the GotFocus event will bubble up to the parent
        // TreeViewItem (which will make it think it's also selected), it
        // needs to ignore that event when it's first been handled by one of
        // its nested children.  We use the IgnoreNextGotFocus flag to
        // notify our parent that GotFocus has already been handled.
        TreeViewItem parent = ParentTreeViewItem;
        if (parent != null)
        {
            parent.CancelGotFocusBubble = true;
        }

        try
        {
            if (Interaction.AllowGotFocus(e) && !CancelGotFocusBubble)
            {
                // Select the item when it's focused
                Select(true);

                // ActivateAsync the selection
                IsSelectionActive = true;
                UpdateVisualState(true);

                Interaction.OnGotFocusBase();
                base.OnGotFocus(e);
            }
        }
        finally
        {
            CancelGotFocusBubble = false;
        }            
    }

从元素获得焦点时我可以看出它有时无法找到它的父节点并阻止在树中向上传播事件。

我还在他们的github存储库上打开了一个issue

答案

正如我之前所说,这似乎是WinRT TreeView组件中的一个错误,但是我设法通过将“IsEnabled”属性从我的ViewModel绑定到IsFiltersOpen属性来防止(硬修复)此行为。

这样,当我选择我的元素时,我会关闭Flyout并禁用TreeView组件,这会阻止它更新。

以上是关于UWP - Flyout中的WinRT xaml工具包TreeView,在弹出窗口关闭后更改选择的主要内容,如果未能解决你的问题,请参考以下文章

切换到其他应用时不会触发 UWP Flyout 的关闭事件

从 Flyout XAML 内的按钮访问 Flyout

如何使用 xaml Themeresource 属性更改 winrt 应用程序的背景颜色和强调颜色

从 UWP 中的自定义 ToolTip 和自定义 Flyout 类取消订阅事件

从代码绑定到 WinRT/UWP 中的自定义附加属性

如何在 UWP 中结合 Flyout 和 MenuFlyout?