Completed
Last Updated: 09 Nov 2020 08:57 by ADMIN
Release 2.20.0
Robert
Created on: 09 Jan 2020 20:27
Category: TreeView
Type: Bug Report
2
Changing treeview data source to one with fewer levels can cause an exception (Cannot access a disposed object)

Repro plus workaround (already in):

<button @onclick="@SwitchDataSource">switch to other data source</button>

<TelerikTreeView Data="@FlatData">
    <TreeViewBindings>
        <TreeViewBinding IdField="Id" ParentIdField="ParentIdValue" ExpandedField="Expanded" TextField="Text" 
                         HasChildrenField="HasChildren" IconField="Icon">
            <ItemTemplate>
                @{
                    TreeItem currProduct = context as TreeItem;
                    @(currProduct.Text)
                }
            </ItemTemplate>
            </TreeViewBinding>
    </TreeViewBindings>
</TelerikTreeView>

@code {
    public class TreeItem
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public int? ParentIdValue { get; set; }
        public bool HasChildren { get; set; }
        public string Icon { get; set; }
        public bool Expanded { get; set; }
    }

    async void SwitchDataSource()
    {
        //workaround - remove it to see the actual error
        foreach (TreeItem item in FlatData)
        {
            item.Expanded = false;
        }
        StateHasChanged();
        await Task.Delay(300);//awaits the animation that will hide the nodes we just collapsed so their elements get properly disposed
        
        //change data
        LoadSecondDataSource();
        //update UI
        StateHasChanged();
    }

    public IEnumerable<TreeItem> FlatData { get; set; }

    protected override void OnInitialized()
    {
        LoadFlatData();
    }

    private void LoadFlatData()
    {
        List<TreeItem> items = new List<TreeItem>();

        items.Add(new TreeItem()
        {
            Id = 1,
            Text = "Project",
            ParentIdValue = null,
            HasChildren = true,
            Icon = "folder",
            Expanded = true
        });

        items.Add(new TreeItem()
        {
            Id = 2,
            Text = "Design",
            ParentIdValue = 1,
            HasChildren = true,
            Icon = "brush",
            Expanded = true
        });
        items.Add(new TreeItem()
        {
            Id = 3,
            Text = "Implementation",
            ParentIdValue = 1,
            HasChildren = true,
            Icon = "folder",
            Expanded = true
        });

        items.Add(new TreeItem()
        {
            Id = 4,
            Text = "site.psd",
            ParentIdValue = 2,
            HasChildren = false,
            Icon = "psd",
            Expanded = true
        });
        items.Add(new TreeItem()
        {
            Id = 5,
            Text = "index.js",
            ParentIdValue = 3,
            HasChildren = false,
            Icon = "js"
        });
        items.Add(new TreeItem()
        {
            Id = 6,
            Text = "index.html",
            ParentIdValue = 3,
            HasChildren = false,
            Icon = "html"
        });
        items.Add(new TreeItem()
        {
            Id = 7,
            Text = "styles.css",
            ParentIdValue = 3,
            HasChildren = false,
            Icon = "css"
        });

        FlatData = items;
    }

    void LoadSecondDataSource()
    {
        List<TreeItem> items = new List<TreeItem>();

        items.Add(new TreeItem()
        {
            Id = 1,
            Text = "1",
            ParentIdValue = null,
            HasChildren = true
        });

        items.Add(new TreeItem()
        {
            Id = 2,
            Text = "1 1",
            ParentIdValue = 1,
            HasChildren = true
        });


        //if you add this, there is no error because the levels match
        //if the new data source does not have the same number of (maybe expanded) levels
        //you will get an error while disposing those levels
        //items.Add(new TreeItem()
        //{
        //    Id = 3,
        //    Text = "1 1 1",
        //    ParentIdValue = 2
        //});



        FlatData = items;
    }
}

0 comments