The TreeView exposes drag events that allow me to detect when the user drags an item and to get the information for the dragged item. I want to be able to drag that item outside of the TreeView and drop it in my custom target.
I am aware that I should handle the custom drop functionality. However, the @ondrop event of my custom target currently does not fire for the tree item: https://blazorrepl.telerik.com/QIblPZvd0412k6U128.
===
ADMIN EDIT
===
For the time being, you may implement the following custom approach:
Here is a basic sample showcasing the approach: https://blazorrepl.telerik.com/QIFbvZFA00bHZbsj23.
This REPL test page is based on the TreeView Filtering demo, but with added checkboxes.
A possible workaround is to also filter (or clear) the collection that is bound to the CheckedItems parameter of the TreeView.
We have the following scenario:
The problem is when you close the dialog before the loading is finished, a NullReferenceException occurs.
System.NullReferenceException: Object reference not set to an instance of an object.
at Telerik.Blazor.Components.Common.Trees.TelerikTreeDataSource.GetTreeItems(IEnumerable`1 data, Int32 level, String parentIndex)
I am trying to restore the expanded items by programmatically populating the ExpandedItems collection of the TreeView.
I have overriden "Equals" on the model, so the items are not compared by reference but by a unique identifier. The problem is that the TelerikTreeView does not respect this override and does not expand the items.
Other controls with similar features do respect overriden implementation of "Equals".
Reproduction: https://blazorrepl.telerik.com/cSuKkqwu46w4sHaW53.
Steps to reproduce:
Expected: Both the parent "Documents" and its 4 children should be checked.
Actual: Only the 4 children are checked; the parent remains unchecked.
This only happens when all children are checked. However, if not all children items are checked, the parent will also be checked.
The TreeView resets the checkbox state of its items when the app adds or removes a node to the component datasource.
A possible workaround is to reset the object reference of the CheckedItems parameter.
The following test page with a workaround is a modified version of TreeView - Refresh Data - Observable Data.
@using System.Collections.ObjectModel
<TelerikButton OnClick="@AddItem">Add Item</TelerikButton>
<TelerikButton OnClick="@RemoveItem">Remove Item</TelerikButton>
<p>
TreeViewCheckedItems Count: @TreeViewCheckedItems.Count()
<br />
<label><TelerikCheckBox @bind-Value="@ApplyWorkaround" /> Apply Workaround</label>
</p>
<TelerikTreeView Data="@TreeViewData"
CheckBoxMode="@TreeViewCheckBoxMode.Multiple"
@bind-CheckedItems="@TreeViewCheckedItems" />
@code {
private IEnumerable<object> TreeViewCheckedItems { get; set; } = new List<TreeItem>();
private ObservableCollection<object> TreeViewData { get; set; } = new ObservableCollection<object>();
private int LastId { get; set; }
private bool ApplyWorkaround { get; set; }
private void AddItem()
{
TreeViewData.Add(
new TreeItem
{
Id = ++LastId,
Text = $"Item {LastId}",
});
if (ApplyWorkaround)
{
TreeViewCheckedItems = new List<object>(TreeViewCheckedItems);
}
}
private void RemoveItem()
{
if (TreeViewData.Count > 1)
{
TreeViewData.Remove(TreeViewData.Last());
if (ApplyWorkaround)
{
TreeViewCheckedItems = new List<object>(TreeViewCheckedItems);
}
}
}
protected override void OnInitialized()
{
TreeViewData = new ObservableCollection<object>() {
new TreeItem()
{
Id = ++LastId,
Text = $"Item {LastId}"
}
};
TreeViewCheckedItems = new List<object>() { TreeViewData.First() };
}
public class TreeItem
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Text { get; set; } = string.Empty;
public bool HasChildren { get; set; }
}
}
asdf
I want to use a separate drag-and-drop mode in the TreeView similar to how the Drag column works for the rows in the Grid component.
The main reason I am unable to use the current drag-and-drop behavior is that I cannot use an input component as part of the TreeView node.
Hi,
Is there a plan to support lines between treeview items as available in radtreeview?
radTreeView1.ShowLines = true;
radTreeView1.LineStyle = TreeLineStyle.DashDot;
Without this it is very confusing to the end user what the connections between open items are.
Regards,
peter
The problem at hand arises when attempting to update the CheckedItems property of a TreeView control from within an async method.
The problem seems to be timing-related and is not always reproducible. The issue is observed most often when starting the project. It seems to be reproducible only in Blazor Server App.
Reproduction:
To reproduce the issue, try running the following snippet in a Blazor Server App.
@page "/"
<TelerikTreeView Data="@FlatData"
CheckBoxMode="@TreeViewCheckBoxMode.Multiple"
CheckParents="@true"
CheckChildren="@true"
CheckOnClick="@false"
@bind-CheckedItems="@SelectedItems">
</TelerikTreeView>
@code {
List<TreeItem> FlatData { get; set; }
IEnumerable<object> SelectedItems { get; set; } = new List<object>();
protected override async Task OnInitializedAsync()
{
await GenerateData();
await SelectDefault();
}
async Task SelectDefault()
{
await Task.Delay(100);
SelectedItems = FlatData.Where(data => data.Id == 2);
}
#pragma warning disable
async Task GenerateData()
{
FlatData = new List<TreeItem>();
FlatData.Add(new TreeItem()
{
Id = 1,
Text = "Project",
ParentId = null,
HasChildren = true,
Icon = "folder",
Expanded = true
});
FlatData.Add(new TreeItem()
{
Id = 2,
Text = "Design",
ParentId = 1,
HasChildren = true,
Icon = "brush",
Expanded = true
});
FlatData.Add(new TreeItem()
{
Id = 3,
Text = "Implementation",
ParentId = 1,
HasChildren = true,
Icon = "folder",
Expanded = true
});
}
public class TreeItem
{
public int Id { get; set; }
public string Text { get; set; }
public int? ParentId { get; set; }
public bool HasChildren { get; set; }
public string Icon { get; set; }
public bool Expanded { get; set; }
}
}
The second TreeItem should be selected.
Checking a checkbox of a on demand-loaded child then collapsing and reopening its parent makes the checkbox disappear. However, it is still checked in the CheckedItems collection, but just not in the UI. See this REPL example. Steps...
1. Expand a top level item
2. Check its child checkbox
3. Collapse the top level item
4. Expand it again
Result: checkbox gone (in the UI)
Hello,
I have a TelerikTreeView with about 2000 items bound to an ObservableCollection (Data). I use SelectedItems, SelectedItemsChanged, SelectionMode multitple and @bind-ExpandedItems.
When my users manually expand the nodes of the treeview, everything is fine and the operation of the treeview works smoothly. Loading UI components based on user selection takes less than 50ms.
As soon as I set the "ExpandedItems" collection from code (according to your treeview demo), the whole treeview operation becomes painfully slow with waiting times of 2 to 4 SECONDS for selection and expansion. Already expanding from code takes several seconds.
As soon as I reset the ExpandedItems from code and collapse the complete tree, the treeview is usable again without delays.
The TreeView has CheckBoxMode="@TreeViewCheckBoxMode.Multiple" and CheckParents="true". Only some checkboxes are checked and there are parent checkboxes in indeterminate state.
When I try to clear all checked checkboxes, the indeterminate checkboxes are not cleared and maintain their state.
ADMIT EDIT:
Initially, this bug report was about unchecking all child items. However, it appears that the opposite behavior exists too - if all children are checked programmatically, the parent checkbox will show as indeterminate. In this case, check the parent explicitly as well.
If the application expands TreeView items programmatically, and then the user tries to select multiple items, an exception will occur.
The issue is a regression that occurred in version 3.0.0. A possible workaround is to Rebind()
the TreeView with a small delay after programmatic item expansion.
<TelerikTreeView @ref="@TreeViewRef"
Data="@FlatData"
@bind-ExpandedItems="@ExpandedItems"
SelectionMode="@TreeViewSelectionMode.Multiple"
SelectedItems="@SelectedItems"
SelectedItemsChanged="@((IEnumerable<object> items) => SelectedItemsHandler(items))" />
<TelerikButton OnClick="@ExpandAll">Expand All</TelerikButton>
<TelerikButton OnClick="@CollapseAll">Collapse All</TelerikButton>
@code {
public TelerikTreeView TreeViewRef { get; set; }
public IEnumerable<TreeItem> FlatData { get; set; }
public IEnumerable<object> SelectedItems { get; set; } = new List<object>();
public IEnumerable<object> ExpandedItems { get; set; } = new List<object>();
async Task ExpandAll()
{
ExpandedItems = FlatData.Where(x => x.HasChildren == true);
await Task.Delay(1);
TreeViewRef.Rebind();
}
void CollapseAll()
{
ExpandedItems = new List<object>();
SelectedItems = new List<object>();
}
void SelectedItemsHandler(IEnumerable<object> items)
{
SelectedItems = items;
}
protected override async void OnInitialized()
{
FlatData = LoadFlat();
}
int TreeLevels { get; set; } = 3;
int ItemsPerLevel { get; set; } = 3;
int IdCounter { get; set; } = 1;
List<TreeItem> LoadFlat()
{
List<TreeItem> items = new List<TreeItem>();
PopulateTreeItems(items, null, 1);
return items;
}
void PopulateTreeItems(List<TreeItem> items, int? parentId, int level)
{
for (int i = 1; i <= ItemsPerLevel; i++)
{
var itemId = IdCounter++;
items.Add(new TreeItem()
{
Id = itemId,
Text = $"Level {level} Item {i} Id {itemId}",
ParentId = parentId,
HasChildren = level < TreeLevels
});
if (level < TreeLevels)
{
PopulateTreeItems(items, itemId, level + 1);
}
}
}
public class TreeItem
{
public int Id { get; set; }
public string Text { get; set; }
public int? ParentId { get; set; }
public bool HasChildren { get; set; }
}
}