Adding Nodes To TreeView In For/ForEach Loop - c#

I've been trying to figure out but it is so complex, so I wanted to ask since I could not get an answer
CheckForIllegalCrossThreadCalls = false;
FolderBrowserDialog fbd = new FolderBrowserDialog();
if(fbd.ShowDialog() == DialogResult.OK)
{
Thread t = new Thread(() => StartListing(fbd.SelectedPath));
SplittedPath = fbd.SelectedPath.Split(Path.DirectorySeparatorChar);
t.Start();
foreach(string s in SplittedPath)
{
if(treeView1.Nodes.Count > 0)
{
treeView1.Nodes[i].Nodes.Add(s);
i++;
treeView1.Nodes[i].ImageIndex = 0;
}
else
{
treeView1.Nodes.Add(s);
treeView1.Nodes[0].ImageIndex = 0;
}
}
}
Here is my code.SplittedPath string is normally seems good.It has all splitted stuff but in ForEach loop, it seems like there are only 2 string.When I delete
if(treeView1.Nodes.Count > 0)
{
treeView1.Nodes[i].Nodes.Add(s);
i++;
treeView1.Nodes[i].ImageIndex = 0;
}
else
{
treeView1.Nodes.Add(s);
treeView1.Nodes[0].ImageIndex = 0;
}
This codes, it just works fine.When I add these to ForEach loop, it just does not add all SplittedPath strings.Any solution?

You don't deal with the tree structure in your code, that's why it doesn't work. You only have 2 levels here.
If you want a tree presentation of your path you should do the following:
TreeNode n = null;
TreeNode parent = null;
foreach(string s in SplittedString)
{
if (parent == null)
{
parent = new TreeNode(s);
treeview1.Nodes.Add(parent);
continue;
}
n = new TreeNode(s);
parent.Nodes.Add(n);
parent = n;
}
I don't say it's the best way to do it, but you have the general idea of an iterative solution.
You get a reference to the parent node, and as you go through your path, the parent changes to be the last node added. That way every string s will be at a different level of your tree structure.

Related

Windows forms Treeview refresh issue

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.

How to do this in c#?

I have a List of MyClass and in the main page I have 10 controls which will display the information about that list of Items. What I want is to check the count of the items in the List and then make the excess controls invisible. Now I'm using this code but is there an easier way of doing this?
if (myList.Count > 0)
{
Control1.MyClassInfo = myList[0];
if (myList.Count > 1)
{
Control2.MyClassInfo = myList[1];
if (myList.Count > 2)
{
// and like that till 10
}
else
{
Control3.Visible = false;
Control4.Visible = false;
// till 10
}
}
else
{
Control2.Visible = false;
Control3.Visible = false;
// till 10
}
}
else
{
Control1.Visible = false;
Control2.Visible = false;
Control3.Visible = false;
// and then till 10
}
Well, just add your controls in a list (ordered).
Something like that
var controlList = new List<Control>{ Control1, Control2, Control3 /*etc*/};
var count = myList.Count;
for (var i = 0; i < controlList.Count; i++) {
controlList[i].Visible = count > i;
}
You could create a list of your controls
List<Control> MyControls = new List<Control>{Control1, Control2,..,Control10};
and then
foreach(var C in MyControls)
C.Visible=false;
for(int i=0; i<myList.Count; i++)
C[i].Visible=true;
EDIT: for the more advanced coders here, this technique is called the Composite Pattern.
Basically, that's it. But you can improve on that basic concept in two ways:
1) use a collection
List<Control> _controls1to10;
Put your controls into that collection and write a method like this:
private void setVisibility(List<Control> _controls, bool visible)
{
foreach (Control c in _controls1to10)
{
c.Visible = visible;
}
}
This will make things easier.
2) use boolean expressions instead of nested ifs, like this:
bool hasElements = myList.Count > 0;
bool hasMoreThan1 = myList.Count > 1;
// ... and so on
This means that you have master switches at the top and use them in the following code. This is a fantasy example to clear the concept but does not apply to your code:
bool isEditable = User.LoggedIn && SystemState.Maintenance == false && item.Count > 0;
editButton.Visible = isEditable;
dropList.Visible = !isEditable;

how to get the second level text from the leaf?

How to get the second father if my position was the leaf .
for example :
1---->2---->3
or
1---->2---->3---->4
or
1---->2---->3---->4---->5
if i'm in the last node (3 or 4 or 5)
How to get the text of node (2)?
foreach (RadTreeNode node in nodeCollection)
{
if (node.Nodes.Count == 0)//leaf
{
if (!node.Value.TrimEnd().Contains('#'))
{
GroupDetails grp_d = new GroupDetails();
grp_d.Boss_code = 0;
grp_d.Boss_name = string.Empty;
if (node.Value.TrimEnd().Split('_').Count() > 2)
{
grp_d.Boss_code = int.Parse(node.Value.TrimEnd().Split('_')[2]);
grp_d.Boss_name = node.Value.TrimEnd().Split('_')[3];
}
grp_d.Dep_code = int.Parse(node.Value.TrimEnd().Split('_')[0]);
grp_d.Dep_name = node.Text.TrimEnd() //Here i want to get the second parent text to concatenate
grp_d.Dep_year = int.Parse(node.Value.TrimEnd().Split('_')[1]);
grp_d.Group_id = res;
grp_det.Add(grp_d);
}
}
}
while( node.parent != null )
node = node.parent;
return node.child;
Assuming you only have one child (i.e. node (2))
Just suggesting a logical way of traversing the tree. Implementation is up to you and your system design!
RadTreeNode node_tmp = new RadTreeNode();
node_tmp = node;
while (node_tmp.ParentNode != null)
{
p_txt = node_tmp.Text.TrimEnd();
node_tmp = node_tmp.ParentNode;
}

How to get all the elements of a WPF TreeView as a List?

I need to access the nodes of a TreeView as a plain list (as if all the nodes where expanded) to be able to do multiselection pressing the Shift key. Is there a way to accomplish this?
Thanks
Here is a method that will retrieve all the TreeViewItems in a TreeView. Please be aware that this is an extremely expensive method to run, as it will have to expand all TreeViewItems nodes and perform an updateLayout each time. As the TreeViewItems are only created when expanding the parent node, there is no other way to do that.
If you only need the list of the nodes that are already opened, you can remove the code that expand them, it will then be much cheaper.
Maybe you should try to find another way to manage multiselection. Having said that, here is the method :
public static List<TreeViewItem> FindTreeViewItems(this Visual #this)
{
if (#this == null)
return null;
var result = new List<TreeViewItem>();
var frameworkElement = #this as FrameworkElement;
if (frameworkElement != null)
{
frameworkElement.ApplyTemplate();
}
Visual child = null;
for (int i = 0, count = VisualTreeHelper.GetChildrenCount(#this); i < count; i++)
{
child = VisualTreeHelper.GetChild(#this, i) as Visual;
var treeViewItem = child as TreeViewItem;
if (treeViewItem != null)
{
result.Add(treeViewItem);
if (!treeViewItem.IsExpanded)
{
treeViewItem.IsExpanded = true;
treeViewItem.UpdateLayout();
}
}
foreach (var childTreeViewItem in FindTreeViewItems(child))
{
result.Add(childTreeViewItem);
}
}
return result;
}
Here is what you asked;
private static TreeViewItem[] getTreeViewItems(TreeView treeView)
{
List<TreeViewItem> returnItems = new List<TreeViewItem>();
for (int x = 0; x < treeView.Items.Count; x++)
{
returnItems.AddRange(getTreeViewItems((TreeViewItem)treeView.Items[x]));
}
return returnItems.ToArray();
}
private static TreeViewItem[] getTreeViewItems(TreeViewItem currentTreeViewItem)
{
List<TreeViewItem> returnItems = new List<TreeViewItem>();
returnItems.Add(currentTreeViewItem);
for (int x = 0; x < currentTreeViewItem.Items.Count; x++)
{
returnItems.AddRange(getTreeViewItems((TreeViewItem)currentTreeViewItem.Items[x]));
}
return returnItems.ToArray();
}
Call with your control as the first parameter e.g.;
getTreeViewItems(treeView1);

How to store child to child nodes and remove the immediate parent?

We are parsing an xml and after serializing them ,it will be stored in database.
Our XML is look like below.
<SampleTypeService>
<Name>sample1</Name>
<URL>sample1</URL>
<SampleTypeService_PK_ID>225d0266-e83a-44b8-88fc-700f6570d530</SampleTypeService_PK_ID>
<SampleTypes>
<SampleType_PK_ID>ef1d8c40-72ce-48d8-b252-9b521e96fa74</SampleType_PK_ID>
</SampleTypes>
</SampleTypeService>
<SampleTypeService>
<Name>sample2</Name>
<URL>sample2</URL>
<SampleTypeService_PK_ID>225reg66-e83a-44b8-88fc-700f6570d530</SampleTypeService_PK_ID>
<SampleTypes>
<SampleType_PK_ID>gh4d8c40-72ce-48d8-b252-9b521e96fa74</SampleType_PK_ID>
</SampleTypes>
</SampleTypeService>
We need to store the value in SampleType_PK_ID in a string and then remove both
SampleTypes and SampleType_PK_ID node.
I am trying to delete it like below.
foreach (XmlNode SampleNode in SampleList)
{
XmlNodeList ChildList = SampleNode.ChildNodes;
for (int j = 0; j < ChildList.Count; j++)
{
if (ChildList[j].LocalName == "SampleType_PK_ID>")
{
strSampleTypePKID = ChildList[j].InnerText;
if (strSampleTypePKID != null)
{
SampleNode.ParentNode.RemoveChild(ChildList[j]);
j--;
}
}
}
testString = SampleNode.OuterXml;
Console.WriteLine("1):" + strSampleTypePKID);
//Code to serialize and store in database is here.
}
But strSampleTypePKID is returning as empty string. What am I missing here. How to take the child to child node value and then delete it along with it's immediate parent?
You're looking for the inner child node "SampleType_PK_ID" at the wrong level.
If you put a breakpoint at the line strSampleTypePKID = ChildList[j].InnerText;, you can see that it's never been executed.
Try the following instead:
foreach (XmlNode SampleNode in doc.FirstChild.ChildNodes)
{
strSampleTypePKID = string.Empty;
var sampleTypesNode = SampleNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "SampleTypes").FirstOrDefault();
if (sampleTypesNode != null)
{
var pkNode = sampleTypesNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "SampleType_PK_ID").FirstOrDefault();
if (pkNode != null)
{
strSampleTypePKID = pkNode.InnerText;
SampleNode.RemoveChild(sampleTypesNode);
}
}
testString = SampleNode.OuterXml;
Console.WriteLine("1):" + strSampleTypePKID);
//Code to serialize and store in database is here.
}

Categories