My setup is basically as follows:
NavigationView
'sMenuItemsSource
is bound toviewModel.NavItems
.NavItems
is a computed property ofviewModel
.
The view model class implements
INotifyPropertyChanged
for binding purposeBooks
of view model is loaded asynchronously.
What works
The NavigationViewItem
s 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;
}
…
}
For async situation, you need use
ObservableCollection
but notList
. And it represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.Before the data is not ready, you could keep the
Frame
navigation to the default page that used as placehoder withinNavigationView
Loaded event. For more you could refer Data binding in depth.