when binding the tree to a collection like
child 2.1.1 -> 2.3.1 won't be visible
some sample code
Create a new project, add the following code and run.
Uncomment the row : // root.Children[0].Children.Add(new NodeItem("hide me and child 2.1.1 -> child 2.3.1 will be invisible"))
---- code:
using System;using System.Collections.ObjectModel;using System.ComponentModel;using System.Windows.Forms;using Infragistics.Win.UltraWinTree; namespace BindTreeTest{ public class Form1 : Form { /// <summary> /// Required designer variable. /// </summary> private readonly IContainer components = null; private UltraTree ultraTree1; public Form1() { this.InitializeComponent(); var root = new NodeItem("root"); root.Children.Add(new NodeItem("child 1")); root.Children.Add(new NodeItem("child 2")); // if this node is hidden, the child 2.1.1 -> 2.1.3 nodes will not be visible // root.Children[0].Children.Add(new NodeItem("hide me and child 2.1.1 -> child 2.1.3 will be invisible")); root.Children[1].Children.Add(new NodeItem("child 2.1")); root.Children[1].Children.Add(new NodeItem("child 2.2")); root.Children[1].Children.Add(new NodeItem("child 2.3")); root.Children[1].Children[0].Children.Add(new NodeItem("child 2.1.1")); root.Children[1].Children[1].Children.Add(new NodeItem("child 2.2.1")); root.Children[1].Children[2].Children.Add(new NodeItem("child 2.3.1")); var collection = new ObservableCollection<NodeItem> {root}; this.ultraTree1.DataSource = collection; this.ultraTree1.ExpandAll(); } /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (this.components != null)) { this.components.Dispose(); } base.Dispose(disposing); } private void ultraTree1_ColumnSetGenerated(object sender, ColumnSetGeneratedEventArgs e) { e.ColumnSet.NodeTextColumn = e.ColumnSet.Columns["Text"]; } /// <summary> /// The main entry point for the application. /// </summary> [STAThread] private static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { var _override1 = new Infragistics.Win.UltraWinTree.Override(); this.ultraTree1 = new Infragistics.Win.UltraWinTree.UltraTree(); ((System.ComponentModel.ISupportInitialize) (this.ultraTree1)).BeginInit(); this.SuspendLayout(); // // ultraTree1 // this.ultraTree1.Dock = System.Windows.Forms.DockStyle.Fill; this.ultraTree1.Location = new System.Drawing.Point(0, 0); this.ultraTree1.Name = "ultraTree1"; _override1.ShowExpansionIndicator = Infragistics.Win.UltraWinTree.ShowExpansionIndicator.CheckOnDisplay; this.ultraTree1.Override = _override1; this.ultraTree1.Size = new System.Drawing.Size(579, 432); this.ultraTree1.TabIndex = 0; this.ultraTree1.ViewStyle = Infragistics.Win.UltraWinTree.ViewStyle.Standard; this.ultraTree1.ColumnSetGenerated += new Infragistics.Win.UltraWinTree.ColumnSetGeneratedEventHandler(this.ultraTree1_ColumnSetGenerated); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(579, 432); this.Controls.Add(this.ultraTree1); this.Name = "Form1"; this.Text = "Form1"; ((System.ComponentModel.ISupportInitialize) (this.ultraTree1)).EndInit(); this.ResumeLayout(false); } #endregion #region Nested type: NodeItem public class NodeItem : NodeItemBase { public NodeItem(string text) : base(text) { } } #endregion #region Nested type: NodeItemBase public abstract class NodeItemBase { protected NodeItemBase(string text) { this.Children = new ObservableCollection<NodeItemBase>(); this.Text = text; } public string Text { get; set; } public ObservableCollection<NodeItemBase> Children { get; private set; } } #endregion }}
Hi Mike,
The ObservableCollection class is now standard in .NET 4.0
I've uploaded a sample project, replaced the ObservableCollection to a BindingList and upgraded to the latest ServiceRelease. Still doesn't work.
Hi,
Perhaps I'm confused about the issue. I ran your sample and I can see the "child 2.1.3" node in the tree. It shows up just fine. Are you saying that on your machine, you cannot see it?
Do I have to do something with the sample to get the problem to occur. There's a note here about hiding the node under Child 1. What do you mean by "hide?" Do you mean collapse the child 1 node? I tried this and it works just fine.
Or actually set the node's Visible property to false? If so, where are you doing this? There's no code in the sample that refers to a node that I can see.
Hi mike,
please comment out / remove line 18 :
root.Children[0].Children.Add(new NodeItem("hide me and child 2.1.1 -> child 2.1.3 will be invisible"));
if you run the code again, child 2.1.1, child 2.1.2, and child 2.1.3 will be invisible!!!
Ah, okay, that makes sense.
The is a problem with the code. The problem is here:
public BindingList<NodeItemBase> Children { get; private set; }
If you are going to use this class for DataBinding, then the child collection cannot be allowed to return null. What's happening here is that the tree creates the root node and then child 1. But when it creates the child 1 node, it automatically generates a column set based on the data structure returned by the DotNet BindingManager. Since this is the first level 1 node the BindingManager has encountered, it's going to base the data structure on this node, and since the Children property returns null, it assumes that there is nothing passed this level. Therefore, all of the other Level 1 nodes in the tree fail to show any children.
Fix the Children property so that it always returns a BindingList (even if it's empty), and the will fix it.
private BindingList<NodeItemBase> children = null; public BindingList<NodeItemBase> Children { get { if (this.children == null) this.children = new BindingList<NodeItemBase>(); return this.children; } private set { this.children = value; } }
This corrects the problem only on one level, though. The first three levels will then display correctly. But the fourth level fails to display at this point, and I am not sure why. It seems to work fine in the WinGrid, so it looks like there may be a bug in the tree here.
I'm going to forward this thread over to Infragistics Developer Support so they can check it out.
Sorry about that, I must have missed that line of code.
The weird thing is that when I changed the code as I suggested above, and made the Children property with a lazy getter, it actually did change the behavior in a very noticeable way. I wonder why.
Anyway, since the grid is working okay here and the tree is not, I think there probably is some kind of bug in the tree, so I'm going to go ahead and have developer support write this up so we can look into it more thoroughly.
Dear Mike,
there is nothing wrong with the code. The children collection is never null since it will be initialized in the constructor:
public abstract class NodeItemBase { protected NodeItemBase(string text) { this.Children = new BindingList<NodeItemBase>(); this.Text = text; } public string Text { get; set; } public BindingList<NodeItemBase> Children { get; private set; } }
The objects are created before the tree is binded, so every object has been gone through the constructor.
if you setup the DataNodeInitialize event and you can do a debug.write on the childrencollection.count and you'll see
every child will be having a ChildrenCollection which has a size of >= 0