How to programmatically select a bound `NavigationViewItem` of `NavigationView` after binding is updated

痞子三分冷 提交于 2019-12-24 17:10:08

问题


My setup is basically as follows:

  • NavigationView's MenuItemsSource is bound to viewModel.NavItems.

    • NavItems is a computed property of viewModel.
  • The view model class implements INotifyPropertyChanged for binding purpose

  • Books of view model is loaded asynchronously.

What works

The NavigationViewItems show up after the page is reached.

The Problem

I need to set a specified NavigationViewItem as the SelectedItem of the NavigationView. But there's no NavigationViewItem (from viewModel) to use inside OnNavigatedTo(NavigationEventArgs e), because at that point viewModel.NavItems is not ready yet.

So is there a pattern for selecting a NavigationViewItem in this async situation?

XAML

<NavigationView x:Name="navView" 
                MenuItemsSource="{x:Bind viewModel.NavItems, Mode=OneWay}"
                SelectionChanged="NavView_SelectionChanged" >
…

the view model

internal class MainPageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        // The data service
        private MainDataService mainDataService = new MainDataService();

        private List<Book> books = new List<Book>();
        public List<Book> Books
        {
            get
            {
                return this.books;
            }
            set
            {
                this.books = value;
                this.OnPropertyChanged();
                this.OnPropertyChanged("NavItems");
            }
        }

        public IEnumerable<NavigationViewItemBase> NavItems
        {
            get
            {
                return Books.SelectMany(
                    b => (new List<NavigationViewItemBase> { new NavigationViewItemHeader {
                        Content = b.Title,
                        Tag = b.Title
                    } })
                    .Concat(
                        b.Sections.Select(s => new NavigationViewItem
                        {
                            Content = s.Title,
                            Icon = new FontIcon { Glyph = "\uE8B7", FontFamily = new FontFamily("Segoe MDL2 Assets") }
                        })
                    )
                );
            }
        }

        // @param selectedBookIndex: the index of the book whose first section
        // should be selected.
        public async Task UpdateBooks(int selectedBookIndex)
        {
            await mainDataService.PrepareData();
            this.Books = mainDataService.Books;
        }

        …
    }

回答1:


So is there a pattern for selecting a NavigationViewItem in this async situation?

For async situation, you need use ObservableCollection but not List. And it represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.

But there's no NavigationViewItem (from viewModel) to use inside OnNavigatedTo(NavigationEventArgs e), because at that point viewModel.NavItems is not ready yet.

Before the data is not ready, you could keep the Frame navigation to the default page that used as placehoder within NavigationView Loaded event. For more you could refer Data binding in depth.



来源:https://stackoverflow.com/questions/51020208/how-to-programmatically-select-a-bound-navigationviewitem-of-navigationview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!