New to Telerik UI for Blazor? Download free 30-day trial

Menu - Refresh Data

The most common reason you would use an ObservableCollection is to make a component (like a grid, treeview, treelist, dropdown) change or react when you change that collection.

When you want to refresh the component data source like that, there are two important framework behaviors you need to be aware of - when ObservableCollection instances fire events, and how to refresh the data of a component when it is not an observable collection.

In this article:

Observable Data

The Menu does not support binding to observable data. You can currently refresh the component by creating a new collection reference.

Databound components can benefit from live updates - when the data source collection changes, the components should update to reflect that change. Most data-bound components in the Telerik UI for Blazor suite implement such functionality.

When the Data of the component is a collection that implements the INotifyCollectionChanged interface (such as ObservableCollection), the Telerik components subscribe to its CollectionChanged event to make live update. This means that adding items, removing items, or clearing the collection updates the components (its .Add(), .Remove() and .Clear() methods).

The Observable collections fire the CollectionChanged event only when their Add, Remove and Clear methods are called. They do not fire it when you change the value of a field of one of their elements.

New Collection Reference

In Blazor, the framework will fire the OnParametersSet event of a child component (which is how child components can react to outside changes) only when it can detect a change in the object it receives through the corresponding parameter (like Data for the data sources of Telerik components). This detection works as follows:

  • For strings and value types, this happens when their value changes.

  • For reference types (such as data collections like List, or any IEnumerable, and application-specific objects), this happens when the object reference changes.

    Thus, you would usually need to create a new reference for the view-model field (such as TreeViewData = new List<MyTreeViewItem>(theUpdatedDataCollection);) when you want the component to update.

Create new collection reference to refresh the Menu data.

@* Add/remove menu item or change the data collection to see how the Menu reacts to that change. *@

<TelerikButton OnClick="@AddItem">Add menu item</TelerikButton>

<TelerikButton OnClick="@RemoveItem">Remove menu item</TelerikButton>

<TelerikButton OnClick="@LoadData">Load new menu data</TelerikButton>

<TelerikMenu Data="@MenuItems"
             UrlField="@nameof(MenuItem.Page)"
             ItemsField="@nameof(MenuItem.SubSectionList)"
             TextField="@nameof(MenuItem.Section)">
</TelerikMenu>

@code {
    public List<MenuItem> MenuItems { get; set; }

    void AddItem()
    {
        MenuItems.Add(
            new MenuItem()
            {
                Section = "Contact",
                Page = "company/contact"
            });
        MenuItems = new List<MenuItem>(MenuItems);
    }

    void RemoveItem()
    {
        if (MenuItems.Count > 0)
        {
            MenuItems.RemoveAt(MenuItems.IndexOf(MenuItems.Last()));
        }
    }

    void LoadData()
    {
        MenuItems = new List<MenuItem>()
        {
            new MenuItem()
            {
                Section = "First new section", // items that don't have a URL will not render links
                SubSectionList = new List<MenuItem>()
                {
                    new MenuItem()
                    {
                        Section = "First option",
                        Page = "newsection/firstoption"
                    },
                    new MenuItem()
                    {
                        Section = "Second option",
                        Page = "newsection/secondoption"
                    }
                }
            },
            new MenuItem()
            {
                Section = "Second new section"
            }
        };
    }

    public class MenuItem
    {
        public string Section { get; set; }
        public string Page { get; set; }
        public List<MenuItem> SubSectionList { get; set; }
    }

    protected override void OnInitialized()
    {
        MenuItems = new List<MenuItem>()
{
            new MenuItem()
            {
                Section = "Company", // items that don't have a URL will not render links
                SubSectionList = new List<MenuItem>()
{
                    new MenuItem()
                    {
                        Section = "Overview",
                        Page = "company/overview"
                    },
                    new MenuItem()
                    {
                        Section = "Events",
                        Page = "company/events"
                    },
                    new MenuItem()
                    {
                        Section = "Careers",
                        Page = "company/careers"
                    }
                }
            },
            new MenuItem()
            {
                Section = "Services",
                SubSectionList = new List<MenuItem>()
{
                    new MenuItem()
                    {
                        Section = "Consulting",
                        Page = "consultingservices"
                    },
                    new MenuItem()
                    {
                        Section = "Education",
                        Page = "education"
                    }
                }
            }
        };

        base.OnInitialized();
    }
}

See Also

In this article