我目前正在尝试使用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组件,这会阻止它更新。