To reproduce: add a RadTreeView and a RadButton to the form. Use the following code snippet: public Form1() { InitializeComponent(); RadTreeNode node1 = new RadTreeNode(); node1.Text = "SameText"; RadTreeNode node2 = new RadTreeNode(); node2.Text = "SameText"; this.radTreeView1.Nodes.Add(node1); this.radTreeView1.Nodes.Add(node2); this.radTreeView1.SortOrder = SortOrder.Ascending; } private void radButton1_Click(object sender, EventArgs e) { for (int i = this.radTreeView1.Nodes.Count - 1; i > -1; i--) { this.radTreeView1.Nodes.RemoveAt(i); } } Workaround: set the SortOrder property to None before removing the nodes and restore it afterwards private void radButton1_Click(object sender, EventArgs e) { this.radTreeView1.SortOrder = SortOrder.None; for (int i = this.radTreeView1.Nodes.Count - 1; i > -1; i--) { this.radTreeView1.Nodes.RemoveAt(i); } this.radTreeView1.SortOrder = SortOrder.None; }
To reproduce - Add RadTreeView with some nodes to a blank form. - Set the MultiSelect property to true. - Select\Deselect a node with code. Resolution: The SelectedNodeChanged event should not be fired when selected/deselected the node programmatically. We added a new event SelectedNodesChanged which is fired when the SelectedNodes collection changes.
To reproduce: use the following code public class Item { public int Id { get; set; } public string Title { get; set; } public string Tag { get; set; } public Item(int id, string title, string tag) { this.Id = id; this.Title = title; this.Tag = tag; } } public Form1() { InitializeComponent(); List<Item> items = new List<Item>(); items.Add(new Item(1,"a1","x1")); items.Add(new Item(2,"a2","x2")); items.Add(new Item(3,"a3","x3")); items.Add(new Item(4,"b1","y1")); items.Add(new Item(5,"b2","y2")); items.Add(new Item(6,"b3","y3")); this.radTreeView1.DataSource = items; this.radTreeView1.DisplayMember = "Title"; this.radTreeView1.ValueMember = "Id"; radTreeView1.FilterDescriptors.Add(new FilterDescriptor("Tag", FilterOperator.Contains, "y")); } Workaround: use custom filtering: public Form1() { InitializeComponent(); List<Item> items = new List<Item>(); items.Add(new Item(1,"a1","x1")); items.Add(new Item(2,"a2","x2")); items.Add(new Item(3,"a3","x3")); items.Add(new Item(4,"b1","y1")); items.Add(new Item(5,"b2","y2")); items.Add(new Item(6,"b3","y3")); this.radTreeView1.DataSource = items; this.radTreeView1.DisplayMember = "Title"; this.radTreeView1.ValueMember = "Id"; radTreeView1.FilterDescriptors.Add(new FilterDescriptor("Tag", FilterOperator.Contains, "y")); radTreeView1.TreeViewElement.FilterPredicate = FilterNode; } public class Item { public int Id { get; set; } public string Title { get; set; } public string Tag { get; set; } public Item(int id, string title, string tag) { this.Id = id; this.Title = title; this.Tag = tag; } } private bool FilterNode(RadTreeNode node) { Item item = node.DataBoundItem as Item; if (item != null && radTreeView1.FilterDescriptors.Count > 0) { FilterDescriptor fd = radTreeView1.FilterDescriptors[0]; var propertyValue = item.GetType().GetProperty(fd.PropertyName, BindingFlags.Public | BindingFlags.Instance).GetValue(item, null); if (propertyValue.ToString().Contains(fd.Value.ToString())) { return true; } return false; } return false; }
To reproduce: add a hierarchical RadTreeView with several levels. Use the RadTreeNode.Expanded property in order to expand a child node from the bottom levels. Ensure that all parent nodes up to the top are expanded as well. When you run the application, the vertical scroll bar is not displayed. Sub New() InitializeComponent() Me.Size = New Size(234, 188) Dim dt As New DataTable dt.Columns.Add("Id", GetType(String)) dt.Columns.Add("ParentId", GetType(String)) dt.Columns.Add("Name", GetType(String)) Dim uniqueId As String = Guid.NewGuid().ToString() dt.Rows.Add(uniqueId, Nothing, "Node.1") For index = 2 To 5 Dim subUniqueId As String = Guid.NewGuid().ToString() dt.Rows.Add(subUniqueId, uniqueId, "SubNode.1." & index) If index Mod 2 = 0 Then For index2 = 6 * index To 6 * index + 5 Dim subSubUniqueId As String = Guid.NewGuid().ToString() dt.Rows.Add(subSubUniqueId, subUniqueId, "SubSubNode.1." & index & "." & index2) For index3 = 12 * index To 12 * index + 3 Dim subSubSubUniqueId As String = Guid.NewGuid().ToString() dt.Rows.Add(subSubSubUniqueId, subSubUniqueId, "SubSubSubNode.1." & index & "." & index2 & "." & index3) Next Next End If Next Me.RadTreeView1.DataSource = dt Me.RadTreeView1.DisplayMember = "Name" Me.RadTreeView1.ValueMember = "Id" Me.RadTreeView1.RelationBindings.Add(New RelationBinding(dt, "Name", "ParentId", "Id", "Id")) End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim nodeTextToExpand = "SubSubNode.1.4.27" Dim nodeToExpand = Me.RadTreeView1.GetNodeByName(nodeTextToExpand) If nodeToExpand IsNot Nothing Then Expand(nodeToExpand) End If End Sub Private Sub Expand(nodeToExpand As RadTreeNode) nodeToExpand.Expanded = True If nodeToExpand.Parent IsNot Nothing Then Expand(nodeToExpand.Parent) End If End Sub Workaround: start expanding the nodes from the top most level to the bottom most level: Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim nodeTextToExpand = "SubSubNode.1.4.27" Dim nodeToExpand = Me.RadTreeView1.GetNodeByName(nodeTextToExpand) If nodeToExpand IsNot Nothing Then Expand(nodeToExpand) End If While (nodes.Count > 0) nodes.Pop().Expanded = True End While End Sub Dim nodes As New Stack(Of RadTreeNode) Private Sub Expand(nodeToExpand As RadTreeNode) nodes.Push(nodeToExpand) If nodeToExpand.Parent IsNot Nothing Then Expand(nodeToExpand.Parent) End If End Sub
To reproduce: 1. Run Demo application >> TreeView >> Drag & Drop. 2. Change the theme to Windows7 and start dragging a node. The drop hint is missing. Workaround: apply the theme in the Form.Load event after getting the TreeViewElement.ItemDropHint property coming from the ControlDefault theme. RadImageShape hint; private void Form1_Load(object sender, EventArgs e) { hint = this.radTreeView1.TreeViewElement.ItemDropHint; this.radTreeView1.ThemeName = "Windows7"; this.radTreeView1.TreeViewElement.ItemDropHint = hint; }
Workaround: use the NodeFormatting event to set the NodeElement.ExpanderElement.Padding to new Padding(1, 0, 0, 0)
To reproduce: 1.Add a RadTreeView and four RadButton controls. 2.Use the following code snippet: private Random random = new Random(); public Form1() { InitializeComponent(); radTreeView1.AutoSize = true; radTreeView1.TreeViewElement.HorizontalScrollState = ScrollState.AlwaysHide ; radTreeView1.TreeViewElement.DrawBorder = false; } private string NextText() { char[] letters = new char[random.Next(4, 11)]; for (int i = 0; i < letters.Length; ++i) { letters[i] = (char)random.Next('a', 'z' + 1); } letters[0] = char.ToUpper(letters[0]); return new string(letters); } private RadTreeNodeCollection GetRandomNodeCollection() { if (radTreeView1.Nodes.Count == 0) { return radTreeView1.Nodes; } int depth = random.Next(MaxDepth(radTreeView1.Nodes)); var source = radTreeView1.Nodes; while ((depth--) >= 0 && source.Count > 0) { source = source[random.Next(source.Count)].Nodes; } return source; } private static int MaxDepth(RadTreeNodeCollection nodes, int currentDepth = 0) { if (nodes.Count == 0) { return currentDepth; } int max = -1; foreach (var n in nodes) { max = Math.Max(MaxDepth(n.Nodes, currentDepth + 1), max); } return max; } private void UpdateTree(bool clearNodes) { radTreeView1.BeginUpdate(); if (clearNodes) { radTreeView1.Nodes.Clear(); } else { bool makeRoot = false; int count = random.Next(10, 50); for (; count > 0; --count) { makeRoot = random.NextDouble() < 0.23456789; var nodes = makeRoot ? radTreeView1.Nodes : GetRandomNodeCollection(); nodes.Add(NextText()); } } radTreeView1.EndUpdate(); radTreeView1.ExpandAll(); } private void radButton1_Click(object sender, EventArgs e) { UpdateTree(false); } private void radButton2_Click(object sender, EventArgs e) { UpdateTree(true); } private void radButton3_Click(object sender, EventArgs e) { radTreeView1.ExpandAll(); } private void radButton4_Click(object sender, EventArgs e) { radTreeView1.CollapseAll(); } Workaround: instead of clearing nodes, remove one by one: //radTreeView1.Nodes.Clear(); while (radTreeView1.Nodes.Count > 0) { radTreeView1.Nodes.Last().Remove(); }
Step to reproduce: radTreeView1.Nodes["Random Node"].Enabled = false; WORKAROUND: public partial class Form1 : Form { public Form1() { InitializeComponent(); radTreeView1.CreateNodeElement += radTreeView1_CreateNodeElement; } void radTreeView1_CreateNodeElement(object sender, Telerik.WinControls.UI.CreateTreeNodeElementEventArgs e) { e.NodeElement = new MyTreeNodeElement(); } } public class MyTreeNodeElement : TreeNodeElement { protected override Type ThemeEffectiveType { get { return typeof(TreeNodeElement); } } protected override void InitializeFields() { base.InitializeFields(); this.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; } }
To reproduce use the following function to reset the data source of the treeview public void LoadObjects() { radBreadCrumb1.DefaultTreeView = null; tvObjects.DataSource = null; tvObjects.DataSource = GetTable(); tvObjects.DisplayMember = "Name"; tvObjects.ValueMember = "Name"; radBreadCrumb1.DefaultTreeView = tvObjects; } Workaround: public void LoadObjects() { radBreadCrumb1.DefaultTreeView = null; MethodInfo mi = typeof(RadBreadCrumb).GetMethod("value_Selected", BindingFlags.Instance | BindingFlags.NonPublic); Delegate delegateToRemove = Delegate.CreateDelegate(typeof(RadTreeView.RadTreeViewEventHandler), this.radBreadCrumb1, mi); this.tvObjects.TreeViewElement.SelectedNodeChanged -= (RadTreeView.RadTreeViewEventHandler)delegateToRemove; mi = typeof(RadBreadCrumb).GetMethod("value_NodeExpand", BindingFlags.Instance | BindingFlags.NonPublic); delegateToRemove = Delegate.CreateDelegate(typeof(RadTreeView.TreeViewEventHandler), this.radBreadCrumb1, mi); this.tvObjects.TreeViewElement.NodeExpandedChanged -= (RadTreeView.TreeViewEventHandler)delegateToRemove; tvObjects.DataSource = null; tvObjects.DataSource = GetTable(); tvObjects.DisplayMember = "Name"; tvObjects.ValueMember = "Name"; radBreadCrumb1.DefaultTreeView = tvObjects; }
If you set the RadBreadCrumb.DefaultTreeView property to null, all items in the RadBreadCrumb should be cleared. Additionally, the subscription to the SelectedNodeChanged remains although the associated tree view is set to null. Afterwards, if you change the selected node, a NullReferenceException occurs.
To reproduces: add a RadTreeView and set up Object-relational hierarchy. Use the following code: NorthwindEntities context = new NorthwindEntities(); public Form1() { InitializeComponent(); context.Categories.Load(); context.Products.Load(); this.radTreeView1.DataSource = context.Categories.Local.ToBindingList(); this.radTreeView1.DisplayMember = "CategoryName\\ProductName"; this.radTreeView1.ChildMember = "Categories\\Products"; } private void radButton1_Click(object sender, EventArgs e) { this.radTreeView1.ChildMember = "Products\\Categories"; this.radTreeView1.DisplayMember = "ProductName\\CategoryName"; this.radTreeView1.DataSource = context.Products.Local.ToBindingList(); } When you click the RadButton, NullReferenceException occurs. Resolution: Add more descriptive exception message.
To reproduce: protected override void OnLoad(EventArgs e) { base.OnLoad(e); radTreeView1 = new RadTreeView(); radTreeView1.Parent = this; for (int i = 0; i < 5; i++) { RadTreeNode n1 = new RadTreeNode("Node" + i); this.radTreeView1.Nodes.Add(n1); if (i % 2 == 0) { for (int j = 0; j < 2; j++) { RadTreeNode n2 = new RadTreeNode("Node" + i + "." + j); n1.Nodes.Add(n2); if (j % 2 == 0) { for (int k = 0; k < 2; k++) { RadTreeNode n3 = new RadTreeNode("Node" + i + "." + j + "." + k); n2.Nodes.Add(n3); } } } } } radTreeView1.ShowRootLines = false; radTreeView1.ShowLines = false; } Workaround: void radTreeView1_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { if (radTreeView1.ShowLines == false) { if (e.NodeElement.LinesContainerElement.Children.Count > 0) { TreeNodeLineElement lineElement = (TreeNodeLineElement)e.NodeElement.LinesContainerElement.Children[0]; lineElement.Visibility = ElementVisibility.Collapsed; } } }
To reproduce: protected override void OnLoad(EventArgs e) { base.OnLoad(e); radTreeView1 = new RadTreeView(); radTreeView1.Parent = this; for (int i = 0; i < 5; i++) { RadTreeNode n1 = new RadTreeNode("Node" + i); this.radTreeView1.Nodes.Add(n1); if (i % 2 == 0) { for (int j = 0; j < 2; j++) { RadTreeNode n2 = new RadTreeNode("Node" + i + "." + j); n1.Nodes.Add(n2); if (j % 2 == 0) { for (int k = 0; k < 2; k++) { RadTreeNode n3 = new RadTreeNode("Node" + i + "." + j + "." + k); n2.Nodes.Add(n3); } } } } } radTreeView1.ShowRootLines = true; radTreeView1.ShowExpandCollapse = false; radTreeView1.ShowLines = true; } WORKAROUND: void radTreeView1_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { if (radTreeView1.ShowExpandCollapse == false && radTreeView1.ShowRootLines == true) { if (e.Node.Parent == null && e.Node.Nodes.Count >0) { TreeNodeLineElement lineElement = (TreeNodeLineElement)e.NodeElement.LinesContainerElement.Children[0]; lineElement.Visibility = ElementVisibility.Visible; if (e.Node.Index==0) { lineElement.Type = TreeNodeLineElement.LinkType.RightTopAngleShape; } else if (e.Node.Index == radTreeView1.Nodes.Count -1) { lineElement.Type = TreeNodeLineElement.LinkType.RightBottomAngleShape; } } } }
1. Create a new project with RadTreeView 2. Handle the NodeCheckedChanged event 3. Call the ExpandAll method for the checked node when handling this event 4. Run the project and check the first node
To reproduce: 1. Add a RadTreeView and populate it with nodes at design time. 2. Use the following code snippet: Me.RadTreeView1.AllowDefaultContextMenu = True Me.RadTreeView1.RightToLeft = Windows.Forms.RightToLeft.Yes When you run the application and right click over a node, the context menu is not in RTL mode. Workaround: use the ContextMenuOpening event and set the TreeViewDefaultContextMenu.RightToLeft property to Yes. Private Sub RadTreeView1_ContextMenuOpening(sender As Object, e As TreeViewContextMenuOpeningEventArgs) _ Handles RadTreeView1.ContextMenuOpening Dim defaultMenu As TreeViewDefaultContextMenu = TryCast(e.Menu, TreeViewDefaultContextMenu) If defaultMenu IsNot Nothing Then defaultMenu.DropDown.RightToLeft = Windows.Forms.RightToLeft.Yes End If End Sub
Workaround: class MyTreeView : RadTreeView { protected override RadTreeViewElement CreateTreeViewElement() { return new MyTreeViewElement(); } public override string ThemeClassName { get { return typeof(RadTreeView).FullName; } } } class MyTreeViewElement : RadTreeViewElement { bool IsPerformingEndEdit = false; protected override bool EndEditCore(bool commitChanges) { if (!IsEditing || IsPerformingEndEdit) { return false; } TreeNodeElement nodeElement = GetElement(this.SelectedNode); if (nodeElement == null) { return false; } this.IsPerformingEndEdit = true; if (commitChanges && this.ActiveEditor.IsModified) { SaveEditorValue(nodeElement, this.ActiveEditor.Value); } this.ActiveEditor.EndEdit(); nodeElement.RemoveEditor(this.ActiveEditor); this.InvalidateMeasure(); UpdateLayout(); OnEdited(new TreeNodeEditedEventArgs(nodeElement, ActiveEditor, !commitChanges)); typeof(RadTreeViewElement).GetField("activeEditor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(this, null); this.IsPerformingEndEdit = false; return false; } protected override Type ThemeEffectiveType { get { return typeof(RadTreeViewElement); } } }
it appears to work okay on android, but I can't use it from an ipad
RadTreeView - Traverser throws exception if you clear and recreate all sub nodes of some node. Steps to reproduce: 1. Create RadTreeView with one node. 2. Add 100 sub nodes. 3. Clear the sub nodes. 4. Move scroll. WorkAround: private void RefreshNodes() { radTreeView1.BeginUpdate(); this.radTreeView1.TreeViewElement.Scroller.Traverser.Position = groupNode; this.radTreeView1.TreeViewElement.Scroller.Traverser.Reset(); this.radTreeView1.SelectedNodes.Clear(); groupNode.Nodes.Clear(); AddNodes(groupNode.Nodes, 1, 100); groupNode.Expand(); radTreeView1.EndUpdate(); this.radTreeView1.TreeViewElement.Update(RadTreeViewElement.UpdateActions.Reset); }