Microsoft-ui-xaml: NavigationView SelectedItem issue between PaneFooter and PainContent

Created on 10 Jun 2019  路  29Comments  路  Source: microsoft/microsoft-ui-xaml

Describe the bug
The issue relates with NavigationView main Content list and PaneFooter List. The last item of main Content list and the first item of Footer list do not get selected sometimes when switching between the lists. In the below code the main list is "Pages" and the Footer contains a ListView and you can see both are updating the same value through SelectedItem property. But selecting through items sometimes does not raise the SelectedItem property. I also checked with a Breakpoint.

Steps to reproduce the bug

<MUXC:NavigationView
            Name="navView"
            Grid.Row="1"
            OpenPaneLength="280"
            MenuItemsSource="{Binding Pages}"
            PaneTitle="{StaticResource AppName}"
            Header="{Binding PageHeader}"
            IsSettingsVisible="False"
            IsBackButtonVisible="Auto"
            SelectedItem="{Binding NavigatedItem, Mode=TwoWay, UpdateSourceTrigger=Default}">
            <MUXC:NavigationView.AutoSuggestBox>
                <AutoSuggestBox
                    Name="NavViewSearchBox"
                    QueryIcon="Find"
                    Text="{Binding SearchQuery, Mode=TwoWay, UpdateSourceTrigger=Default}"
                    ItemsSource="{Binding SearchSuggestions, Mode=OneWay, UpdateSourceTrigger=Default}"/>
            </MUXC:NavigationView.AutoSuggestBox>
            <MUXC:NavigationView.PaneFooter>
                <ListView
                    SelectedItem="{Binding NavigatedItem, Mode=TwoWay, UpdateSourceTrigger=Default}">
                    <MUXC:NavigationViewItem
                        Tag="User"
                        Height="80">
                        <RelativePanel
                            HorizontalAlignment="Stretch" VerticalAlignment="Center"
                            Margin="-16,0,0,0" Height="76" Width="280">
                            <RelativePanel.Background>
                                <ImageBrush
                                    Opacity="0.4"
                                    ImageSource="{Binding CurrentUserDetail.UserCoverImageUrl, Mode=OneWay, UpdateSourceTrigger=Default}"/>
                            </RelativePanel.Background>
                            <Ellipse
                                Width="32" Height="32" Name="userImageEllipse"
                                Stroke="{StaticResource ApplicationForegroundThemeBrush}"
                                RelativePanel.AlignLeftWithPanel="True" Margin="4,0,4,0"
                                RelativePanel.AlignVerticalCenterWithPanel="True">
                                <Ellipse.Fill>
                                    <ImageBrush ImageSource="{Binding CurrentUserDetail.UserProfileImageUrl, Mode=OneWay, UpdateSourceTrigger=Default}"/>
                                </Ellipse.Fill>
                            </Ellipse>
                            <TextBlock
                                Name="userNameTB" RelativePanel.RightOf="userImageEllipse"
                                RelativePanel.AlignVerticalCenterWithPanel="True"
                                Text="{Binding CurrentUserDetail.UserName, Mode=OneWay, UpdateSourceTrigger=Default, FallbackValue=User}"/>
                        </RelativePanel>
                    </MUXC:NavigationViewItem>
                    <MUXC:NavigationViewItem
                        Tag="Settings"
                        Content="Settings">
                        <MUXC:NavigationViewItem.Icon>
                            <SymbolIcon Symbol="Setting"/>
                        </MUXC:NavigationViewItem.Icon>
                    </MUXC:NavigationViewItem>
                </ListView>
            </MUXC:NavigationView.PaneFooter>
            <MUXC:NavigationView
                Name="subscriptionsView"
                IsPaneToggleButtonVisible="False"
                PaneDisplayMode="LeftMinimal"
                IsBackButtonVisible="Collapsed"
                IsSettingsVisible="False"
                IsPaneOpen="{Binding IsSubscriptionsPaneOpen, Mode=TwoWay, UpdateSourceTrigger=Default}">
                <MUXC:NavigationView.PaneCustomContent>
                    <local:SubscriptionsView/>
                </MUXC:NavigationView.PaneCustomContent>
                <Frame
                    x:Name="RootFrame"/>
            </MUXC:NavigationView>
        </MUXC:NavigationView>

Steps to reproduce the behavior:

  1. Select items between the two lists intermittently

Expected behavior
The items should be selected just like others

Screenshots
issue

Version Info
OS Version : 18875.rs pre_release
Dell Laptop without Touch

NuGet package version:
Microsoft.UI.Xaml 2.1.190405004.2

| Windows 10 version | Saw the problem? |
| :--------------------------------- | :-------------------- |
| Insider Build (18875) | Yes |
| May 2019 Update (18362)
| October 2018 Update (17763)
| April 2018 Update (17134)
| Fall Creators Update (16299)
| Creators Update (15063)
| Anniversary Update (14393)


| Device form factor | Saw the problem? |
| :-------------------- | :------------------- |
| Desktop | Yes |
| Mobile | |
| Xbox | |
| Surface Hub | |
| IoT | |

area-NavigationView bug help wanted team-Controls

Most helpful comment

I think items in the footer not playing the selection animation is expected. That was actually one of the primary motivations for adding FooterMenuItems, there the selection animation does play.

All 29 comments

This is surprising that this is animating at all, since we've gotten reports that animations into PaneFooter items doesn't work. @yulikl can you follow up on this?

I'm not sure what might be causing this issue but item selected property doesn't get called up sometimes and that causes this to not work. I have not yet tried but I think putting a ItemClicked event in code-behind and then setting the selected item may be a way to work around this for now.

NavigationView's ItemInvoked event is raised when an item within the MenuItems collection gets invoked. The items you've placed in the footer are in a separate ListView and not part of MenuItems, so NavigationView's event won't trigger.

I admit that I'm not sure what you're doing with the SelectedItem binding and why that's working even some of the time. Have you tried setting IsSelected on the NavigationViewItem directly, rather than relying on the parent to select a child item?

Looking at your code snippet, I believe you're looking for #375.

A couple more questions, mostly for my own curiosity and education:

  • Why did you decide to create your own Settings item instead of using the one built into NavigationView?
  • For your subscriptionsView, have you considered using a SplitView instead of NavigationView? (It doesn't appear that you're leveraging any NavigationView features for the nested control, and SplitView doesn't have all of NavigationView's complexity.)

I admit that I'm not sure what you're doing with the SelectedItem binding and why that's working even some of the time. Have you tried setting IsSelected on the NavigationViewItem directly, rather than relying on the parent to select a child item?

Well I didnt really think aboutit much at start becasue the items in both lists are of type NavigationViewItem and the property which is being bound to is of type object and it was working (partially) and I thought it was a bug but now it turns out the functionality is not even there. Anyway about your suggestion I dont think I can implement it properly since I'll need to keep track of last item and current item to know which one to select or not. On the other hand I am using MVVM and would like to avoid code-behind as much as possible.

  • Why did you decide to create your own Settings item instead of using the one built into NavigationView?

I am using Tag property to navigate between pages but the included settings doesnt have that property, hence my own implementation.

  • For your subscriptionsView, have you considered using a SplitView instead of NavigationView? (It doesn't appear that you're leveraging any NavigationView features for the nested control, and SplitView doesn't have all of NavigationView's complexity.)

Yes, you are right. I found out that NavigationView does not support scrolling even in a ListView so I had to switch back to SplitView for that.

Discussed with @yulikl and we'll use this issue to track the problem where item in the main area gets clicked on and the selection indicator goes to Home instead of the one that was clicked.

Discussed with @YuliKl and we'll use this issue to track the problem where item in the main area gets clicked on and the selection indicator goes to Home instead of the one that was clicked.

That would actually be a waste of time becasue as my implementation goes that is expected behavior in my app. As you may see in the gif image, another pane was open and once the pane hides the navigation item gets set to the current page (from code). It is just how I am doing it. Sorry for the confusion here.

Oh ok, thanks for clarifying. So do you think #855 and #375 would cover the issues you're seeing?

Yes I think those are enough to go on but in my situation the selection is working along with the indicator animation but is a little inconsistent and sometimes the selected item doesn't get invoked. Do you think this issue will be resolved once the proper support has been added?
If your answer is yes then I'll have to revert back to SplitView for my case scenario until this gets added.

is a little inconsistent and sometimes the selected item doesn't get invoked. Do you think this issue will be resolved once the proper support has been added?

No, I think that what you're hitting is a another problem and that's what I wanted this issue to track. :) So does your sample code above fully reproduce this problem if i just drop that into a blank UWP app and try to click around? Sometimes I'll see the selected item not get invoked?

We had a bug that was just fixed (#573) where clicking on the same item twice wouldn't fire the invoked event. That's now in the latest 2.1 package so you could try that and see if it's improved?

Yes I believe that it should be that way because in my app I am still experiencing the same issue. As I am using the SelectedItem property, I really don't wanna use the ItemInvoked event handler.

Also I think I am using the beta version of the package but the issue is present even in the stable build. If you want to reproduce the issue then you can use the above code with NavigationViewItems in a list and bound to the navigation view.

If you can make a standalone repro app (either attached to the issue or in a standalone github repo) that would make it a lot faster for us to diagnose. Or if you have an app we can install and debug through, we could use that too.

If you can make a standalone repro app (either attached to the issue or in a standalone github repo) that would make it a lot faster for us to diagnose. Or if you have an app we can install and debug through, we could use that too.

I am not really using any special cases for this. The UI is same as it has been provided above and for the main list I use the below code in my ViewModel to generate data.

private ObservableCollection<object> pages;
public ObservableCollection<object> Pages { get => pages; set { if (value != pages) { pages = value; OnPropertyChanged(); } } }

private object navigatedItem;
public object NavigatedItem
        {
            get => navigatedItem;
            set { if (value != navigatedItem) { navigatedItem = value; OnPropertyChanged(); NavigatePage(value); } }
        }

private void AddNavigationPages()
        {
            if (Pages == null)
            {
                Pages = new ObservableCollection<object>();
            }
            //Pages.Add(new muxc.NavigationViewItemHeader() { Tag = "browse", Content = "Browse" });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.Home, Content = "Home", Icon = new SymbolIcon(Symbol.Home) });

            Pages.Add(new muxc.NavigationViewItemHeader() { Tag = EnumService.PageViews.ManageHeader, Content = "Manage", Name = "manageHeader" });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.Subscriptions, Content = "Subscriptions", Icon = new SymbolIcon((Symbol)0xE728) });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.Create, Content = "Create", Icon = new SymbolIcon((Symbol)0xE948) });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.History, Content = "History", Icon = new SymbolIcon((Symbol)0xE81C) });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.SavedOffline, Content = "Saved Offline", Icon = new SymbolIcon((Symbol)0xE896) });

            Pages.Add(new muxc.NavigationViewItemHeader() { Tag = EnumService.PageViews.AnalyseHeader, Content = "Analyse", Name = "analyseHeader" });
            Pages.Add(new muxc.NavigationViewItem() { Tag = EnumService.PageViews.Analytics, Content = "Analytics", Icon = new SymbolIcon((Symbol)0xE9D9) });

            NavigatedItem = Pages.FirstOrDefault() as muxc.NavigationViewItem;
        }

The Pages collection is for main list while footer list has its own set of items and NavigatedItem is for the current selected navigation item binding. Hopefully you can reproduce the issue on your own.

I believe the above behavior is somewhat expected behavior for the scenario because there are two completely different lists in play here. That said, I think the first time any item can be selected because both lists have SelectedItem as null but then once you start selecting items you can not go back to the last item you selected in the other list. For example if your current item was Analytics then you chose Settings so now the main list has a last selection of Analytics so when you try to select it again there is no response but you can select any other item from the main list.

Although I am using the same Binding for both lists, the system however seems to be keeping a separate copy for both of them and that is why the behavior seems inconsistent. I think I can work round it with using two distinctive Bindings and then assigning them Null value when switching lists. Or maybe someone has a better idea?

Thanks @ahmar20! I don't know when our team will get a chance to look into this, but I think we have what we need now.

@ranjeshj @StephenLPeters Do you think it is still worth looking into this given that we now have FooteMenuItems?

Does this mean you've confirmed that it still reproduces?

Setting NavView.SelectedItem seems to animate correctly, setting IsSeletced on items in the pane footer does not work though.

I think items in the footer not playing the selection animation is expected. That was actually one of the primary motivations for adding FooterMenuItems, there the selection animation does play.

If the animation not working for the PaneFooter is by design, I don't think there is anything to investigate here. I wasn't able to repro the behavior of some items not being selectable.

@ahmar20 latest 2.5.0 prerelease contains FooterMenu implementation. Does this solve your problem?

Setting NavView.SelectedItem seems to animate correctly, setting IsSeletced on items in the pane footer does not work though.

This seems like a bug right? regardless of how the item gets selected the selection indicator should behave the same

Hmm that's a good point, the indicator should at least be visible. Though if I recall correctly, the NavigationView also handles this to a degree, so a missing animation is usually accompanied by a missing selection indicator.

@ahmar20 latest 2.5.0 prerelease contains FooterMenu implementation. Does this solve your problem?

I have not had the time to look at it in a while. If it has been implemented, then this issue can be closed.

It does seem weird to show the selection indicator and selection animation for the main menu items and the settings item, but not the footer items that go in between them.

The question here is, whether we still aim to support putting them in the panefooter instead of using the new FooterItems API here. There are arguments for both sides here. Fact is that the FooterItems work fine, however NavViewItems in the PaneFooter are only partially functional.

I think the reason why the pane footer configuration is not really working is based on the fact that the NavViewItems are "bound" to their containing NavigationView. Howver, the NavView items only get notified who their owning NavView is when they are in the MenuItems or FooterItems or they are the SettingsItem since in those cases, the NavView will tell them that as soon as they are being realized. The NavView does not do this for elements on the panefooter because there might be some NavView items, but most of the time, there panefooter does not contain them.

I see. I think its fine to leave this as is and recommend using FooterItems/FooterItemsSource. @YuliKl should we deprecate this property now that we have FooterItems/FooterItemsSource (remove it in WinUI4 )

The panefooter is where we suggest placing things which are not nav view items, like app branding or a button or something. I don't think we are suggesting removing it.

I think we should either not allow nav view items in the pane footer (or strongly encourage against it) or fix the selection issue.

Definitely not remove the PaneFooter API as that allows us to place (interactive) elements inside the NavigationView pane which do not participate in the selection model (like @StephenLPeters said).

I think we should either not allow nav view items in the pane footer (or strongly encourage against it) or fix the selection issue.

Adding a note to the existing emarks section for the PaneFooter API documentation sounds good to me. It could read roughly like this, for example:

"A NavigationViewItem placed in the PaneFooter does not take part in the NavigationView selection model. If selection is required, please use the FooterMenuItems API (with link to the API)."

While no functionality would be lost if we were to outright disallow NavigationViewItems to be placed inside the PaneFooter (they can be placed inside the new FooterMenuItems area with SelectsOnInvoked set to false), that would be a breaking change so I don't think it's worth it. I also wouldn't fix the selection issue for NavigationViewItems in the PaneFooter.

To summarize:
If developers want to place a NavigationViewItem in the footer area which does not participate in the selection, they can use either the PaneFooter area or the FooterMenuItems area. The documentation should call out that if a "footer-placed" NavigationViewItem is meant to take part in the NavigationView selection model, then it has to be placed inside the new FooterMenuItems area.

@ranjeshj @StephenLPeters Should we close this issue than and update the documentation to point out that placing items in the PaneFooter is discouraged and those items should be placed in the FooterItems? Regarding prohibiting it, I am not sure what we can do, after all items could be placed in other elements and then we would need the entire visual tree to check if users used NavView items in the PaneFooter and not the FooterItems.

Was this page helpful?
0 / 5 - 0 ratings