I am currently trying to use WinRT xaml ToolKit TreeView component since it is not supported in UWP natively.
TreeView is inside a button Flyout. When I press the button I want Flyout to appear so I can select an item from the tree. And I bind a command from ViewModel to SelectedItemChanged event:
<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>
After I select an item from TreeView, SelectedItemChanged event fires as it should, but afterwards I close the Flyout and the event fires again. The second time it usually fires saying new selected element is next after current's parent. So for example if I have this structure:
1
--1.0
--1.1
--1.2
2
--2.0
--2.1
So if I select --1.1 first SelectedItemChanged will fire with --1.1 element, and afterwards it will fire with 2 as new selected item.
Note: I am using CustomFlyout component which I can close from ViewModel, but I also tested this with regular Flyout and same thing happens after I close Flyout by clicking outside of it.
UPDATE: I've downloaded WinRT code and started debugging the TreeView component locally. In TreeViewItem.cs I've found the source of the problem in this function:
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;
}
}
From what I can tell when element gets focus sometimes it fails to find it's parent and prevent propagating the event upwards in the tree.
I've also opened an issue on their github repository