0

Sample : link

I'm developing an application that allows people to save notes, and create categories in which you can store your notes.

Categories are listed in a List, and an ObservableCollection, because I had a problem, trying to serialize a List of NavigationViewItems. So I made the following class:

[DataContract]
class Category
{
    [DataMember]
    public String Title { get; set; }

    [DataMember]
    public int IconIndex { get; set; }

    [DataMember]
    public String Id { get; set; }
}

And in my App.xaml.cs I have:

internal static ObservableCollection<NavigationViewItem> Categories = new ObservableCollection<NavigationViewItem>();
internal static List<Category> CategoriesItems = new List<Category>();

Categories (the ObservableCollection) is used as my NavigationView's MenuItemsSource :

nav.MenuItemsSource = App.Categories;

In an other file, I have a function called OpenCategories, called at the opening of the application:

public async static void OpenCategories(StorageFile file)
{
    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(await FileIO.ReadTextAsync(file)));
    DataContractJsonSerializer ser = new DataContractJsonSerializer(App.CategoriesItems.GetType());
    App.CategoriesItems = ser.ReadObject(ms) as List<Category>;
    ms.Close();

    UIServices.RefreshCategoriesUI();
}

And here's UIServices.RefreshCategoriesUI() :

public static void RefreshCategoriesUI()
{
    App.Categories = new System.Collections.ObjectModel.ObservableCollection<NavigationViewItem>();
    foreach(Category cat in App.CategoriesItems)
    {
        App.Categories.Add(new NavigationViewItem
        {
            Content = cat.Title,
            Icon = new SymbolIcon((Symbol)Enum.GetValues(typeof(Symbol)).GetValue(cat.IconIndex))
        });
    }
}

=> My issue is that even though App.Categories contains NavigationViewItems, my NavigationViewMenu is always empty. Why isn't it updating ?

Edit : Here are the changes I made.

Categories has been moved from App.xaml.cs to MainPage.xaml and has been transformed into a DependencyProperty

internal DependencyProperty CategoriesProperty = DependencyProperty.Register("CategoriesProperty", typeof(ObservableCollection<NavigationViewItem>), typeof(App), new PropertyMetadata(default(ObservableCollection<NavigationViewItem>)));

RefreshCategoriesUI is not used anymore. Instead, I turned CategoriesItems into a ObservableCollection property and subscribed to the CollectionChanged event:

private void CategoriesItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    var page = (MainPage)((Frame)Window.Current.Content).Content;
    page.Categories = new ObservableCollection<NavigationViewItem>();
    foreach (Category cat in CategoriesItems)
        page.Categories.Add(new NavigationViewItem
        {
            Content = cat.Title,
            Icon = new SymbolIcon((Symbol)Enum.GetValues(typeof(Symbol)).GetValue(cat.IconIndex))
        });
}

And finally OpenCategories is now working this way:

public async static void OpenCategories(StorageFile file)
{
    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(await FileIO.ReadTextAsync(file)));
    DataContractJsonSerializer ser = new DataContractJsonSerializer(App.CategoriesItems.GetType());
    ObservableCollection<Category> categories = ser.ReadObject(ms) as ObservableCollection<Category>;
    foreach (Category cat in categories)
        App.CategoriesItems.Add(cat);
    ms.Close();
}

Oh and it seems obvious but I changed the MenuItemSource of my NavigationView from App.Categories to Categories, as Categories moved.

It's still not working. And when I check during runtime, Categories contains all the categories I created through my app.

Moreover, it's really weird because when I first checked if Categories contained something (to write this post), after my breakpoint, all the categories popped up in the NavigationView as it's supposed to do everytime, but when I tried again it didn't work.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • Hello, Your App.Categories must be a dependency property. It's a special kind of property made to link a UI component to a property in your logic. I think you will need to move your Categories property to your Page.xaml.cs, otherwise the dependency property may not work (I'm saying that from head). This link must help : https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/custom-dependency-properties – Veler Jan 03 '18 at 16:04
  • Could you provide a simple sample that can reproduce your this issue? – Breeze Liu - MSFT Jan 04 '18 at 07:25
  • @BreezeLiu-MSFT I'm making a sample currently, but it's even more strange, now (on my sample), categories are displayed each time I open my app, and if I had a new category during runtime, this new category will only display at the next time I open my app – christophechichmanian Jan 04 '18 at 15:18
  • @christophechichmanian Could you share the sample? Can you see whether the category has been added into the categories when the category doesn't display ? – Breeze Liu - MSFT Jan 05 '18 at 01:36
  • @BreezeLiu-MSFT sorry I wasn't that much available before. I added a link to download the sample at the starting of my main post. Oh and by the way, thank you so much for taking your time to help me ! – christophechichmanian Jan 06 '18 at 00:28

1 Answers1

0

For your sample, in the App.xaml.cs file CategoriesItems_CollectionChanged method, every time there is a CollectionChanged event triggers, you create a new ObservableCollection<NavigationViewItem> object then add the items into it, but you should also set the NavigationView.MenuItemsSource to the ObservableCollection again.

You can try to change your CategoriesItems_CollectionChanged method as the following.

private void CategoriesItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    // Gets the MainPage
    var page = (MainPage)((Frame)Window.Current.Content).Content;
    page.Categories = new ObservableCollection<NavigationViewItem>();

    // Creates all the NavigationViewItems, based on CategoriesItems
    foreach (Category cat in CategoriesItems)
        page.Categories.Add(new NavigationViewItem
        {
            Content = cat.Title,
            Icon = new SymbolIcon((Symbol)Enum.GetValues(typeof(Symbol)).GetValue(cat.IconIndex))
        });

    //Here is the code to set the NavigationView's MenuItemsSource.

    NavigationView nav= (NavigationView)page.FindName("nav");
    nav.MenuItemsSource = page.Categories;
}
Breeze Liu - MSFT
  • 3,734
  • 1
  • 10
  • 13