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;
}
}