UWP - WinRT xaml Flyout 中的工具包 TreeView,在 flyout 关闭后更改选择
UWP - WinRT xaml toolkit TreeView in Flyout, changes selection after flyout closes
我目前正在尝试使用 WinRT xaml ToolKit TreeView 组件,因为 UWP 本机不支持它。
TreeView 在按钮 Flyout 中。当我按下按钮时,我希望 Flyout 出现,这样我就可以 select 树中的一个项目。然后我将命令从 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>
在我 select TreeView 中的一个项目之后,SelectedItemChanged 事件按预期触发,但之后我关闭 Flyout 并再次触发该事件。第二次它通常会触发说新的 selected 元素在当前的父元素之后。例如,如果我有这个结构:
1
--1.0
--1.1
--1.2
2
--2.0
--2.1
所以如果我 select --1.1 第一个 SelectedItemChanged 将触发 --1.1 元素,然后它将触发 2 作为新的 selected 项目。
注意:我使用的是 CustomFlyout 组件,我可以从 ViewModel 中关闭它,但我也使用常规 Flyout 对此进行了测试,同样的事情发生在我通过单击外部 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" 属性 绑定到 IsFiltersOpen 属性 来防止(硬修复)此行为我的视图模型。
这样,当我 select 我的元素时,我关闭 Flyout 并禁用 TreeView 组件,这会阻止它更新。
我目前正在尝试使用 WinRT xaml ToolKit TreeView 组件,因为 UWP 本机不支持它。
TreeView 在按钮 Flyout 中。当我按下按钮时,我希望 Flyout 出现,这样我就可以 select 树中的一个项目。然后我将命令从 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>
在我 select TreeView 中的一个项目之后,SelectedItemChanged 事件按预期触发,但之后我关闭 Flyout 并再次触发该事件。第二次它通常会触发说新的 selected 元素在当前的父元素之后。例如,如果我有这个结构:
1
--1.0
--1.1
--1.2
2
--2.0
--2.1
所以如果我 select --1.1 第一个 SelectedItemChanged 将触发 --1.1 元素,然后它将触发 2 作为新的 selected 项目。
注意:我使用的是 CustomFlyout 组件,我可以从 ViewModel 中关闭它,但我也使用常规 Flyout 对此进行了测试,同样的事情发生在我通过单击外部 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" 属性 绑定到 IsFiltersOpen 属性 来防止(硬修复)此行为我的视图模型。
这样,当我 select 我的元素时,我关闭 Flyout 并禁用 TreeView 组件,这会阻止它更新。