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); } } }
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(); }
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; }
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
it appears to work okay on android, but I can't use it from an ipad
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 some notes to RadTreeView. Set the Font as follows in the NodeFormatting event: Font font = new Font("Tahoma", 13f); void tree_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { e.NodeElement.ContentElement.Font = font; } Start the project on Windows 7 or Vista with ClearType off and you will see that the font is thick. Workaround: Use the following node element: public class MyTreeNodeElement : TreeNodeElement { protected override TreeNodeContentElement CreateContentElement() { return new MyTreeNodeContentElement(); } protected override Type ThemeEffectiveType { get { return typeof(TreeNodeElement); } } } public class MyTreeNodeContentElement : TreeNodeContentElement { protected override void PrePaintElement(Telerik.WinControls.Paint.IGraphics graphics) { base.PrePaintElement(graphics); Graphics g = graphics.UnderlayGraphics as Graphics; if (g == null) { return; } if (this.Enabled) { g.TextRenderingHint = this.TextRenderingHint; } else { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; } } } void tree_CreateNodeElement(object sender, CreateTreeNodeElementEventArgs e) { e.NodeElement = new MyTreeNodeElement(); } And set the TextRenderingHint of the ContentElement: Font font = new Font("Tahoma", 13f); void tree_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { e.NodeElement.ContentElement.Font = font; e.NodeElement.ContentElement.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; }
To reproduce : add a RadTreeView with several nodes and use the following code snippet: this.radTreeView1.AllowDragDrop = true; this.TopMost = true; Note that dragging a node will no longer display the "DropHint" line. Workaround: class CustomDragDropService : TreeViewDragDropService { public CustomDragDropService(RadTreeViewElement owner) : base(owner) { } protected override void UpdateHintPosition(Point mousePosition) { FieldInfo fi = typeof(TreeViewDragDropService).GetField("dropHintWindow", BindingFlags.NonPublic | BindingFlags.Instance); RadLayeredWindow window = fi.GetValue(this) as RadLayeredWindow; window.TopMost = true; base.UpdateHintPosition(mousePosition); } } class CustomTreeViewElement : RadTreeViewElement { //Enable themeing for the element protected override Type ThemeEffectiveType { get { return typeof(RadTreeViewElement); } } //Replace the default drag drop service with the custom one protected override TreeViewDragDropService CreateDragDropService() { return new CustomDragDropService(this); } } class CustomTreeView : RadTreeView { //Replace the default element with the custom one protected override RadTreeViewElement CreateTreeViewElement() { return new CustomTreeViewElement(); } //Enable theming for the control public override string ThemeClassName { get { return typeof(RadTreeView).FullName; } } }
To reproduce: - Add RadTreeView to a blank form. - Set its AllowDragDrop and AllowDefaultContextMenu properties to true. - Clear the menu items in the ContextMenuOpening event. - You will notice that the Copy, Cut and Paste items are not removed. Workaround: void radTreeView1_ContextMenuOpening(object sender, Telerik.WinControls.UI.TreeViewContextMenuOpeningEventArgs e) { e.Menu.DropDownOpened -= Menu_DropDownOpened; e.Menu.DropDownOpened += Menu_DropDownOpened; } void Menu_DropDownOpened(object sender, EventArgs e) { TreeViewDefaultContextMenu Menu = sender as TreeViewDefaultContextMenu; for (int i = Menu.Items.Count - 1; i >= 0; i--) { if (Menu.Items[i].Name == "Copy" || Menu.Items[i].Name == "Cut" || Menu.Items[i].Name == "Paste") { Menu.Items.Remove(Menu.Items[i]); } } }
The disabling of the scroll bars is broke as shit. I have tried rtvDrainage.HorizontalScroll.Visible = false; rtvDrainage.HorizontalScroll.Maximum = 0; rtvDrainage.HorizontalScroll.Enabled = false; rtvDrainage.AutoScroll = false; rtvDrainage.EnableDeferredScrolling = false; rtvDrainage.EnableKineticScrolling = false; rtvDrainage.HScrollBar.Maximum = 0; rtvDrainage.HScrollBar.Visibility = Telerik.WinControls.ElementVisibility.Collapsed; NOTHING stops this damn thing from showing up (i put this in both the load and in a button to hit after loading) 2 hours wasted trying to make a scroll bar not show up.........
To reproduce: Use the following code on an empty RadTreeView: this.TreeView.AddNodeByPath("General\\Billing\\February\\Report.txt"); You will see that the Report.txt node will be added to the Root node Workaround: Use the following method: private RadTreeNodeCollection AddNode(string path) { if (path == String.Empty) return this.TreeView.Nodes; string node = Path.GetFileName(path); RadTreeNodeCollection parent = AddNode(Path.GetDirectoryName(path)); if (parent.Contains(node)) return parent[node].Nodes; else return parent.Add(node).Nodes; }
Add a RadTreeView with several hierarchy levels. Initially all nodes are collapsed. When you collapse each child node deeper in the hierarchy, use the following code snippet: public Form1() { InitializeComponent(); radTreeView1.CollapseAll(); radTreeView1.TreeViewElement.AutoScrollOnClick = false; } private void radTreeView1_NodeExpandedChanged(object sender, RadTreeViewEventArgs e) { if (e.Node.Expanded) { e.Node.LastNode.EnsureVisible(); radTreeView1.BringIntoView(e.Node.LastNode); } } The last child node is visible, regarding the height, however, the entire node is not visible, regarding the width. Workaround: use RadTreeView.MouseUp event instead. private void radTreeView1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { TreeNodeExpanderItem expander = radTreeView1.ElementTree.GetElementAtPoint(e.Location) as TreeNodeExpanderItem; if (expander != null && expander.Expanded && expander.NodeElement.Data != null) { radTreeView1.BringIntoView(expander.NodeElement.Data.LastNode); } } }
To reproduce: - Add treeview to a form and set its AutoScrollOnClick property to false. - click a node that is not entirely visible with the right mouse button. - You will notice that the view is auto scrolled.
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: 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; } } } }
To reproduce: Add nodes to RadTreeView with at least 3 levels hierarchy. Set some of the last level nodes Visible property to false. Start the application. Expand some nodes and scroll. You will notice that the last item will change sometimes. Workaround: Set this.radTreeView1.TreeViewElement.AllowArbitraryItemHeight = true; Use ItemHeight = 1, instead of Visible = false
Start dragging a node and scroll using the mouse wheel. While scrolling, drop the node.
To reproduce: -add RadTreeView and RadButton: -use the following code: public partial class Form1 : Form { public Form1() { InitializeComponent(); List<Distributor> distributors = new List<Distributor>() { new Distributor(432,"Distributor 1"), new Distributor(454,"Distributor 2"), new Distributor(438,"Distributor 3"), new Distributor(455,"Distributor 4") }; List<Distributor> distributors2 = new List<Distributor>() { new Distributor(486,"Distributor 5"), new Distributor(487,"Distributor 6"), new Distributor(498,"Distributor 7"), new Distributor(475,"Distributor 8") }; List<Product> products = new List<Product>(); products.Add(new Product(567, "Bicycle", 5, distributors)); products.Add(new Product(456, "Car", 5000,distributors2)); products.Add(new Product(789, "Bike", 1500,null)); BindingList<Category> categories = new BindingList<Category>(); categories.Add(new Category("Bikes", products)); categories.Add(new Category("Accessories", null)); categories.Add(new Category("Clothing", null)); radTreeView1.DataSource = categories; if ((radTreeView1.DataSource as BindingList<Category>).Count > 0) { radTreeView1.DisplayMember = "Name\\Description\\Name"; radTreeView1.ChildMember = "Categories\\Products\\Distributors"; } } private void radButton1_Click(object sender, EventArgs e) { BindingList<Category> categories = radTreeView1.DataSource as BindingList<Category>; categories.Clear(); } } public class Distributor { private int _id; private string _name; public Distributor(int id, string name) { this._id = id; this._name = name; } public int Id { get { return this._id; } set { this._id = value; } } public string Name { get { return this._name; } set { this._name = value; } } } public class Product { private int _id; private string _description; private float _price; private List<Distributor> _distributors; public List<Distributor> Distributors { get { return this._distributors; } set { this._distributors = value; } } public int ID { get { return _id; } set { _id = value; } } public string Description { get { return _description; } set { _description = value; } } public float Price { get { return _price; } set { _price = value; } } public Product(int id, string description, float price, List<Distributor> distributors) { _id = id; _description = description; _price = price; _distributors = distributors; } } public class Category { public Category(string name, List<Product> products) { _name = name; _products = products; } private List<Product> _products; private string _name; public string Name { get { return _name; } set { _name = value; } } public List<Product> Products { get { return _products; } set { _products = value; } } } When you click the button, ArgumentOutOfRangeException is thrown. Workaround: instead of clearing the BindingList, remove each list item one by one: while (categories.Count>0) { categories.RemoveAt(0); }
To reproduce: Add a RadTreeView and a Timer(from the Windows.Forms namespace). Set the timer's interval to some short duration and add nodes to tree on its tick event. Scroll the thumb while the timer is ticking. At some point you will notice that the scrollbar's maximum value is not correct. Workaround: Do not add nodes while scrolling: List<string> cachedValues = new List<string>(); System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer() { Interval = 100 }; void radTreeView1_MouseCaptureChanged(object sender, EventArgs e) { timer.Start(); } void timer_Tick(object sender, EventArgs e) { timer.Stop(); if (this.cachedValues.Count > 0 && !radTreeView1.TreeViewElement.Scroller.Scrollbar.ThumbElement.Capture) { foreach (string value in this.cachedValues) { root.Nodes.Add(value); } cachedValues.Clear(); } } private void timerUpdateNodes_Tick(object sender, EventArgs e) { for (int i = 0; i < 10; ++i) { if (random.NextDouble() < .2) { if (radTreeView1.TreeViewElement.Scroller.Scrollbar.ThumbElement.Capture) { cachedValues.Add("Node"); } else { root.Nodes.Add("Node"); } } } }