Windows forms Treeview refresh issue - c#

I am using a TreeView to show a folderstructure. I dynamically create nodes in the NodeMouseClick event.
But even though the child nodes are populated, they are not visible in the treeview.
However, minimizing the window and maximizing it again solves this issue. Please let me know what I am doing wrong here. Please find below the code that I am using:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (treeView1.SelectedNode != null && e.Node.IsExpanded)
{
treeView1.BeginUpdate();
TreeNode node = e.Node;
while (node.Parent != null)
{
node = node.Parent;
}
VcDetailsEntity detailsEntity = connectedVCs.Where(c => c.VCName == node.Name).FirstOrDefault();
detailsEntity.VCBrowserPath = e.Node.Name;
FolderBrowser cosmosBrowser = new FolderBrowser();
List<FolderStreamEntity> folderStreams = folderBrowser.GetVcContentDetails(detailsEntity);
e.Node.Nodes.Clear();
foreach (var stream in folderStreams)
{
if (stream.IsDirectory)
{
TreeNode treeNode = new TreeNode();
treeNode.Name = stream.StreamName;
treeNode.Text = stream.QualifiedName;
treeNode.ToolTipText = stream.QualifiedName;
TreeNode dummyNode = new TreeNode();
treeNode.Nodes.Add((TreeNode)dummyNode.Clone());
TreeNode toUpdate = treeView1.Nodes.Find(e.Node.Name, true).FirstOrDefault();
toUpdate.Nodes.Add((TreeNode)treeNode.Clone());
}
}
treeView1.EndUpdate();
treeView1.Refresh();
}
}
I have tried the suggestions provided by Gnial0id, wpfnoop and LarsTech here below. But no luck. Temporarily I have resolved it by minimizing and maximizing the form programatically.

Well, it's hard to figure out anything from the provided code snippet because many parts are missing. Also I don't quite understand why TreeNode toUpdate = treeView1.Nodes.Find(e.Node.Name, true).FirstOrDefault(); is needed and then why you are cloning the node you just created etc. So I've prepared a sample test which is doing something similar and it does not experience the problem you are describing. Check it out and compare it to your code to find out what is wrong.
using System;
using System.Windows.Forms;
namespace Samples
{
static class Test
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form();
var treeView = new TreeView { Dock = DockStyle.Fill, Parent = form };
for (int i = 1; i <= 10; i++)
{
var parent = new TreeNode { Text = "Parent#" + i };
treeView.Nodes.Add(parent);
for (int j = 1; j <= 10; j++)
{
var child = new TreeNode { Text = "Child#" + i };
var dummy = new TreeNode();
child.Nodes.Add(dummy);
parent.Nodes.Add(child);
}
}
var random = new Random();
int addCount = 0;
treeView.NodeMouseClick += (sender, e) =>
{
if (treeView.SelectedNode == e.Node && e.Node.IsExpanded)
{
treeView.BeginUpdate();
e.Node.Nodes.Clear();
int count = random.Next(20) + 1;
for (int i = 1; i <= count; i++)
{
var child = new TreeNode { Text = "AddChild#" + (++addCount) };
var dummy = new TreeNode();
child.Nodes.Add(dummy);
e.Node.Nodes.Add(child);
}
treeView.EndUpdate();
}
};
Application.Run(form);
}
}
}

Adding below code bloc immediately after the code to add a New Node did the magic for me.
treeView1.SelectedNode = NodeToUpdate;
Here the NodeToUpdate is the node where the new child nodes are added.

Related

C# Create Tracks Parents which Depend on Children

I'm trying to create tracks of Parent that have more than a child and put theme in dynamic ListBox
i have this ParentActivity table"
tblParentActivity
and I want to make tracks depend on ParentActivity table to be in ListBox like this:
Tracks in ListBox
the code so far:
private void TrackingActivity(long ParentActivityID)
{
DataTable dtActiveChild = objA.SelectActivityChild(ParentActivityID);
ListBox lstBox = new ListBox();
lstBox.ID = "lstTrack" + ParentActivityID.ToString();
lstBox.Width = 200;
pnlTrack.Controls.Add(lstBox);
for (int i = 0; i < dtActiveChild.Rows.Count; i++)
{
long ActivityChildID = Convert.ToInt64(dtActiveChild.Rows[i]["ActivityID"].ToString());
string ActivityChildName = dtActiveChild.Rows[i]["ActivityName"].ToString();
lstBox.Items.Add(new ListItem (ActivityChildName.ToString(),ActivityChildID.ToString()));
DataTable dtBrotherActivity = objA.selectBrotherActivity(ActivityChildID);
if (dtBrotherActivity.Rows.Count > 0)
{
TrackingActivity(ActivityChildID);
}
}
}
for example ParentActivityID=1;
selectBrotherActivity is query to get another child of it parent
it gave me distribution like this:
|1|2 3|4 5|7|9|10|7|9|10|6|8|9|10|
which || means ListBox
Ok thanks to everyone I found it:
protected void btnCreateTrack_Click(object sender, EventArgs e)
{
ListBox lstBoxParent = new ListBox();
lstBoxParent.ID = "lstTrack1";
lstBoxParent.Width = 200;
lstBoxParent.Height = 200;
pnlTrack.Controls.Add(lstBoxParent);
TrackingActivity(1, lstBoxParent );
}
private void TrackingActivity(long ParentActivityID, ListBox lstBoxParent)
{
chk:
DataTable dtActiveChild = objWFAI.SelectActivityChild(ParentActivityID);
string ActivityName = objWFA.CurrentActivityName(ParentActivityID);
lstBoxParent.Items.Add(new ListItem(ActivityName, ParentActivityID.ToString()));
for (int i = dtActiveChild .Rows.Count - 1; i >= 0; i--)
{
long ActivityChildID = Convert.ToInt64(dtActiveChild .Rows[i][" ActivityID"].ToString());
if (i != 0)
{
ListBox lstBoxChild = new ListBox();
lstBoxChild.ID = "lstTrack" + ActivityChildID.ToString();
lstBoxChild.Width = 200;
lstBoxChild.Height = 200;
pnlTrack.Controls.Add(lstBoxChild);
for (int p = 0; p < lstBoxParent.Items.Count; p++)
{
lstBoxChild.Items.Add(new ListItem(lstBoxParent.Items[p].Text, lstBoxParent.Items[p].Value));
}
TrackingActivity(ActivityChildID, lstBoxChild);
}
else
{
ParentActivityID = ActivityChildID ;
goto chk;
}
}

Get value from dynamically generated textboxes to XML

I added 89 textboxes dynamically. I want to get the value of the textboxes to xml. I can add the textboxes just fine the problem is I cant get the values on those dynamically
added textboxes.
For example i want to get value from textBox1 to the node "F1" in XML ,from textBox2 to node "F2" in XML.
private void button1_Click(object sender, EventArgs e)
{
XmlNodeList xnList;
XmlDocument doc = new XmlDocument();
string dosyayolu = Application.StartupPath + "\\coupling.xml";
doc.Load(dosyayolu);
if (globaller.hangimenu == "TWT1")
{
xnList = doc.SelectNodes("/coup/TWT1");
}
else
{
xnList = doc.SelectNodes("/coup/TWT2");
}
for (int i = 0; i < 89; i++)
{
foreach (XmlNode xn in xnList)
{
xn["F" + (i + 1).ToString()].InnerText = "k";
// xn["F1"].InnerText = textBox1.Text;
}
}
doc.Save(dosyayolu);
}
You could use the extension ChildrenOfType<T>().
Assuming that grid is the parent of all your TextBoxes..
var textBoxes= grid.ChildrenOfType<TextBox>().ToArray();
for (int i = 0; i < 89; i++)
{
foreach (XmlNode xn in xnList)
{
xn["F" + (i + 1).ToString()].InnerText = "k";
xn["F1"].InnerText = textBoxes[ i ].Text;
}
}
i'm guessing your textboxes are of name textBox1, textBox2, .... also your xml nodes start on F1 instead of F2 so i altered the For loop a bit
for (int i = 1; i < 90; i++)
{
foreach (XmlNode xn in xnList)
{
// this if textboxes on form, yourUserControlName if it is under a usercontrol
var tb = (TextBox)this.Controls["textBox" + i];
xn["F" + i].InnerText = tb.Text;
}
}
Edited in favor of comment of Hassan Nisar
you can do it like this:
//create
StackPanel sp = new StackPanel();
for(int i=0;i<89;i++)
{
TextBox tb = new TextBox();
sp.Children.Add(tb);
}
//get
foreach(TextBox tb in sp.Children)
{
}
or you can add all the textboxs to a list,and get them from list by index

StackOverflowException in recursive ASP.NET treeview population

I have a custom ASP.NET treeview control, which uses existing MS Treeview. I create and recreate the treeview upon postbacks (it is in UpdatePanel) from a stored IEnumerable.
Some items are added like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack && !Page.IsAsync)
{
DD.Items = null;
DD.Items.Add(new TreeviewItem("Choice 1", "4", "-1"));// = items;
DD.Items.Add(new TreeviewItem("something", "1", "-1"));
DD.Items.Add(new TreeviewItem("Europe", "2", "-1"));
DD.Items.Add(new TreeviewItem("pff", "3", "-1"));
}}
The control is initialized and loaded in it's OnLoad using BuildTreeFromItemCollection():
public void BuildTreeFromItemCollection()
{
BuildTreeFromItemCollection(this.Items, null);
}
public void BuildTreeFromItemCollection(IEnumerable<StoredItem> items, TreeNode parentNode)
{
IEnumerable<TreeviewItem> tvItems = items.Cast<TreeviewItem>();
var nodes = tvItems.Where(x => parentNode == null ? int.Parse(x.Parent) <= 0 : x.Parent == parentNode.Value);
TreeNode childNode;
foreach (var i in nodes)
{
childNode = new TreeNode(i.Name, i.Value)
{
PopulateOnDemand = this.PopulateOnDemand
};
if (parentNode == null)
{
TvHierarchy.Nodes.Add(childNode);
}
else
{
parentNode.ChildNodes.Add(childNode);
}
this.BuildTreeFromItemCollection(items, childNode);
}
}
TreeNodePopulate is handled like so:
void TvHierarchy_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
this.EnsureChildControls();
IEnumerable<StoredItem> childItems = NodePopulator(e.Node.Value);
foreach (StoredItem item in childItems)
{
TreeNode newNode = new TreeNode(item.Name, item.Value);
newNode.PopulateOnDemand = this.PopulateOnDemand;
e.Node.ChildNodes.Add(newNode);
}
this.Items.AddRange(childItems);
}
and this Func is temporarily attached to the NodePopulator:
private IEnumerable<StoredItem> ItemLoader(string val)
{
List<StoredItem> itemList = new List<StoredItem>();
Random r = new Random();
for (int i = 0; i <= 4; i++)
{
int rand = r.Next(10,100);
itemList.Add(new TreeviewItem("test " + rand.ToString(), rand.ToString(), val));
}
return itemList;
}
Unfortunately the BuildTreeFromItemCollection falls into infinite loop after a couple of node expansions, around 4th level, and i'm left with stack overflow.
The exact exception shows up on the line
var nodes = tvItems.Where(x => parentNode == null ? int.Parse(x.Parent) <= 0 : x.Parent == parentNode.Value);
but the Call stack looks already filled up. Where's the problem?
So it seems that the whole problem was in the code generating new nodes in this test function:
int rand = r.Next(10,100);
itemList.Add(new TreeviewItem("test " + rand.ToString(), rand.ToString(), val));
So when an ID was generated which already was earlier the code went into infinite loop. After expanding range to (10,10000) everything works fine.

Access items in listbox in windows phone 7?

In my code,
protected override void OnNavigatedTo(NavigationEventArgs e)
{
using (bus_noContext ctx = new bus_noContext(bus_noContext.ConnectionString))
{
ctx.CreateIfNotExists();
ctx.LogDebug = true;
var buses = from c in ctx.Bus_routes
select new bus_list{ BUS_NO = c.BUS_NO, SOURCE = c.SOURCE, DESTINATION = c.DESTINATION};
busno_list.ItemsSource = buses.ToList();
}
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string temp;
TextBlock nameBox;
ListBoxItem currentSelectedListBoxItem;
for(int i=0;i<busno_list.Items.Count;i++)
{
currentSelectedListBoxItem = this.busno_list.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
nameBox = FindDescendant<TextBlock>(currentSelectedListBoxItem);
temp = nameBox.Text;
if (temp.Contains(searchbox.Text))
{
busno_list.SelectedIndex = i;
busno_list.ScrollIntoView(busno_list.SelectedItem);
return;
}
}
}
and in FindDescendant function ,
private T FindDescendant<T>(DependencyObject obj) where T : DependencyObject
{
// Check if this object is the specified type
if (obj is T)
return obj as T;
// Check for children
int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
if (childrenCount < 1)
return null;
// First check all the children
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child is T)
return child as T;
}
// Then check the childrens children
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = FindDescendant<T>(VisualTreeHelper.GetChild(obj, i));
if (child != null && child is T)
return child as T;
}
return null;
}
But at the line
int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
debugger is always throwing InvalidOperationException (Reference is not a valid visual DependencyObject) and in Autos watch tool, obj is showing null value, even if there are already 557 rows in listbox.
So I am not able to correct this exception.
And i find this method best for searching through the listbox having datatemplate as given on How to access a specific item in a Listbox with DataTemplate?. Please suggest where i am going wrong or if there is a better alternative.
Not sure why you're trying to do this by finding the generated element, when you have the source, i.e. something like:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
using (bus_noContext ctx = new bus_noContext(bus_noContext.ConnectionString))
{
ctx.CreateIfNotExists();
ctx.LogDebug = true;
var buses = from c in ctx.Bus_routes
select new bus_list{ BUS_NO = c.BUS_NO, SOURCE = c.SOURCE, DESTINATION = c.DESTINATION};
busno_list.ItemsSource = buses.ToList();
searchbox.Text = buses[20].SOURCE; // or whatever
}
}

how to add items to TreeViewAdv in multi-column mode with winforms

I was playing around with this control called TreeViewAdv. I've already added the control and added couple of columns trying to see how it works. but till now when I add items to the control all I get is empty nodes. the example provided with the control is not clear at all and it just gave me headaches when I try to figure out how the data is being added to it. anyway here is what I've done so far and I hope that someone can guide me to the right direction.
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new MyNode("child" + n);
parentNode.Nodes.Add(childNode);
}
}
treeViewAdv1.EndUpdate();
anyway, all I'm getting is empty nodes and I really can't figure out how to add data to the other columns... any help would be appreciated...
Obviously this questions is old, but I was unable to find any answers to this question, so I figured I would try to save someone some future frustration.
To get multiple columns to display, first change the UseColumns property to true.
Then add desired columms to the Columns collection property.
Next using the NodeControls collection property to create a list of the types of data that will be shown, and how they should be formatted (Checkbox, TextBox, etc). Make sure to set 1) the DataPropertyName (will be used later), 2) the ParentColumn (to show which column in the treeView is supposed to show the data.
Finally, create a new class inheriting from the Node class, and add a public property with the same name as each NodeControl. Then when adding Nodes, use your new class with the correct value.
private class ColumnNode: Node
{
public string NodeControl1=""; // This sould make the DataPropertyName specified in the Node Collection.
public string NodeControl2 = "";
public string NodeControl3 = "";
public ColumnNode(string nodeControl1, string nodeControl2, int nodeControl3)
{
NodeControl1 = nodeControl1;
NodeControl2 = nodeControl2;
NodeControl3 = nodeControl3.ToString();
}
}
Then when adding the
TreeModel _model = new TreeModel();
_treeViewAdv.Model = _model;
_treeViewAdv.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new ColumnNode("root" + i, "",0);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new ColumnNode("child" + n,"Further Information",1);
parentNode.Nodes.Add(childNode);
}
}
_treeViewAdv.EndUpdate();
For reference, the designer code for the treeViewAdv in this case would look like this:
private Aga.Controls.Tree.TreeViewAdv _treeViewAdv;
private Aga.Controls.Tree.TreeColumn Column1;
private Aga.Controls.Tree.TreeColumn Column2;
private Aga.Controls.Tree.TreeColumn Column3;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl1;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl2;
private Aga.Controls.Tree.NodeControls.NodeTextBox NodeControl3;
private InitializeComponent()
{
// Left out all other initialization, since this was long enough already.
this.treeViewAdvPrint = new Aga.Controls.Tree.TreeViewAdv();
this.Column1 = new Aga.Controls.Tree.TreeColumn();
this.Column2 = new Aga.Controls.Tree.TreeColumn();
this.Column3 = new Aga.Controls.Tree.TreeColumn();
this.NodeControl1 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl2 = new Aga.Controls.Tree.NodeControls.NodeTextBox();
this.NodeControl3= new Aga.Controls.Tree.NodeControls.NodeTextBox();
//
// _treeViewAdv
//
this._treeViewAdv.BackColor = System.Drawing.SystemColors.Window;
this._treeViewAdv.Columns.Add(this.Column1);
this._treeViewAdv.Columns.Add(this.Column2);
this._treeViewAdv.Columns.Add(this.Column3);
this._treeViewAdv.DefaultToolTipProvider = null;
this._treeViewAdv.DragDropMarkColor = System.Drawing.Color.Black;
this._treeViewAdv.GridLineStyle = ((Aga.Controls.Tree.GridLineStyle)((Aga.Controls.Tree.GridLineStyle.Horizontal | Aga.Controls.Tree.GridLineStyle.Vertical)));
this._treeViewAdv.LineColor = System.Drawing.SystemColors.ControlDark;
this._treeViewAdv.Location = new System.Drawing.Point(12, 12);
this._treeViewAdv.Model = null;
this._treeViewAdv.Name = "_treeViewAdv";
this._treeViewAdv.NodeControls.Add(NodeControl1);
this._treeViewAdv.NodeControls.Add(NodeControl2);
this._treeViewAdv.NodeControls.Add(NodeControl3);
this._treeViewAdv.SelectedNode = null;
this._treeViewAdv.Size = new System.Drawing.Size(443, 356);
this._treeViewAdv.TabIndex = 6;
this._treeViewAdv.Text = "_treeViewAdv";
this._treeViewAdv.UseColumns = true;
//
// Column1
//
this.Column1.Header = "Column 1";
this.Column1.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column1.TooltipText = null;
this.Column1.Width = 290;
//
// Column3
//
this.Column3.Header = "Column 3";
this.Column3.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column3.TooltipText = null;
//
// Column2
//
this.Column2.Header = "Column 2";
this.Column2.SortOrder = System.Windows.Forms.SortOrder.None;
this.Column2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.Column2.TooltipText = null;
this.Column2.Width = 91;
//
// NodeControl1
//
this.NodeControl1.DataPropertyName = "NodeControl1";
this.NodeControl1.IncrementalSearchEnabled = true;
this.NodeControl1.LeftMargin = 3;
this.NodeControl1.ParentColumn = this.Column1;
//
// NodeControl2
//
this.NodeControl2.DataPropertyName = "NodeControl2";
this.NodeControl2.IncrementalSearchEnabled = true;
this.NodeControl2.LeftMargin = 3;
this.NodeControl2.ParentColumn = this.Column2;
//
// NodeControl3
//
this.NodeControl3.DataPropertyName = "NodeControl3";
this.NodeControl3.IncrementalSearchEnabled = true;
this.NodeControl3.LeftMargin = 3;
this.NodeControl3.ParentColumn = this.Column3;
}
It seems as though the price of entry for using this fantastic control is hours, and hours, of head scratching frustration.
This is what you need to do:
private void Form1_Load(object sender, EventArgs e)
{
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
for (int i = 0; i < 20; i++)
{
Node parentNode = new Node("root" + i);
_model.Nodes.Add(parentNode);
for (int n = 0; n < 2; n++)
{
Node childNode = new Node("child" + n);
parentNode.Nodes.Add(childNode);
}
}
NodeTextBox ntb = new NodeTextBox();
ntb.DataPropertyName = "Text";
this.treeViewAdv1.NodeControls.Add(ntb);
treeViewAdv1.EndUpdate();
}
Just in case you're still struggling with the issue, or anyone else is having the same trouble: the solution to empty nodes is to assign a view component to tree.
TreeViewAdv uses MVC, and it requires that you assign a view, though this is not obvious from the example project. NodeTextBox class under NodeControls folder in the source of the TreeViewAdv is one of the viewers you can use. You need to add it to your form and connect it to tree control through its DataPropertyName attribute like this:
this._tBox.DataPropertyName = "Text";
where _tBox is the NodeTextBox instance. Needless to say, I've just lost hours figuring this out. Hope it helps someone else.
You need to instantiate your columns first, then attach them to the TreeView. After all add new cells in all columns at same cell index.
Hope to help

Categories