This is the code which I am using, but I am always getting a blank string from the function.
How do I solve such a problem?
private string GetArrayofCheckedNodes()
{
string arrCheckedNodes = "";
ArrayList al = new ArrayList();
foreach (TreeNode node in TreeView1.Nodes)
{
if (node.Checked == true) // Checking whether a node is checked or not.
{
al.Add(node.Text);
}
}
for (int i = 0; i < al.Count; i++)
{
arrCheckedNodes += al[i].ToString() + " , ";
}
return arrCheckedNodes;
}
I'm assuming you want ALL checked nodes. TreeView1.Nodes only returns the first level so you will need to recurse down the tree. Also, you can use string.Join() to join the resultant values together.
private string GetArrayofCheckedNodes()
{
return string.Join(" , ", GetCheckedNodes(treeView1.Nodes));
}
public List<string> GetCheckedNodes(TreeNodeCollection nodes)
{
List<string> nodeList = new List<string>();
if (nodes == null)
{
return nodeList;
}
foreach (TreeNode childNode in nodes)
{
if (childNode.Checked)
{
nodeList.Add(childNode.Text);
}
nodeList.AddRange(GetCheckedNodes(childNode.Nodes));
}
return nodeList;
}
I want to traverse through a treeview & set the value property to be its position in the tree as shown below
A[val:1]->A1[val:11]
l l--->A2[val:12]
l----->A3[val:13]
B[val:2]->B1[val:21]
l l--->B2[val:22]
C[val:3]->C1[val:31]
l l--->C2[val:32]
I have written a recursive which returns me all the nodes but i am unable to assign the desired position to its nodes.
private void TraverseTreeNode(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
TraverseTreeNode(node.ChildNodes);
}
}
Considering that TreeNode.Value is of type string, this will, starting at level = 1:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = string.Format("{0}{1}", parentNumber, childNumber ).Substring(0,node.Depth+1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}
Only works for two levels but is easily extendable by adding additional parameters to TraverseTreeNode.
UPDATE
The following will work for any depth in hierarchy:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = node.Parent != null && node.Parent.Value != null
? string.Format("{0}{1}", node.Parent.Value, childNumber)
: string.Format("{0}{1}", parentNumber, childNumber).Substring(0, node.Depth + 1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}
As you need recursive method, try this
private void Caller()
{
TraverseTreeNode(treeView1.Nodes);
}
private void TraverseTreeNode(TreeNodeCollection nodes)
{
int index = 1;
foreach (TreeNode node in nodes)
{
node.Text = (node.Parent != null ? node.Parent.Text : string.Empty) + index++;
TraverseTreeNode(node.Nodes);
}
}
I'm working on a Winform application, how can I check if there is a treeNode that its text is inside string Mystring? And how can i retrieve the tag of this node please?
if (myString.Contains(treeView1.Nodes.ToString()))
This works for only first matched node.
private TreeNode FindMatchedNode(TreeNodeCollection tnCol, string text)
{
TreeNode tn = null;
foreach (TreeNode node in tnCol)
{
if (text.ToLower().Contains(node.Text.ToLower()))
{
tn = node;
break;
}
else if (node.Nodes != null)
{
tn = FindNode(node.Nodes, text);
if (tn != null)
break;
}
}
return tn;
}
and for all matched nodes
private List<TreeNode> FindAllMatchedNodes(TreeNodeCollection tnCol, string text)
{
List<TreeNode> retVal = new List<TreeNode>();
foreach (TreeNode node in tnCol)
{
if (text.ToLower().Contains(node.Text.ToLower()))
{
retVal.Add(node);
}
else if (node.Nodes != null)
{
retVal.AddRange(FindNode(node.Nodes, text));
}
}
return retVal;
}
This method will traverse tree from root and find first node that Text is inside of myString
public object FindNode()
{
var queue = new Queue<TreeNode>();
foreach (var n in treeView1.Nodes)
{
// Add all root nodes to queue
queue.Enqueue(n);
}
while (queue.Count > 0)
{
// Take the next node from the front of the queue
var node = queue.Dequeue();
// Check if myString contains node text
if (myString.Contains(node.Text))
return node.Tag;
// Add the node’s children to the back of the queue
foreach (var child in node.Children)
{
queue.Enqueue(child);
}
}
// None of the nodes matched the specified string.
return null;
}
I would like to change the order of System.Windows.Forms.TreeNodes on the same level.
any suggestions on how this might be done in .net-2.0.
You need to manipulate the TreeView's Nodes collection. See TreeNodeCollection.
If you have three tree nodes and you want to move the last one to the front, for example: (Note: not tested code, but shows the idea)
var lastNode = MyTreeView.Nodes[2];
MyTreeView.Nodes.Remove(lastNode);
MyTreeView.Nodes.Insert(0, lastNode);
void MoveNodeUp(TreeNode node)
{
TreeNode parentNode = node.Parent;
int originalIndex = node.Index;
if (node.Index == 0) return;
TreeNode ClonedNode = (TreeNode)node.Clone();
node.Remove();
parentNode.Nodes.Insert(originalIndex - 1, ClonedNode);
parentNode.TreeView.SelectedNode = ClonedNode;
}
That's what I've written:
public void MoveNode(TreeView tv, TreeNode node, bool up)
{
if ((node.PrevNode == null) && up) {
return;
}
if ((node.NextNode == null) && !up) {
return;
}
int newIndex = up ? node.Index - 1 : node.Index + 1;
var nodes = tv.Nodes;
if (node.Parent != null) {
nodes = node.Parent.Nodes;
}
nodes.Remove(node);
nodes.Insert(newIndex, node);
}
I wrote this code which does not require any cloning.
For my case it moves up one position in the sibling nodes but can be adapted
TreeNode selectedNode = treeViewChain.SelectedNode;
if (selectedNode != null && selectedNode.Index > 0)
{
TreeNode parent = selectedNode.Parent;
int selectedIndex = selectedNode.Index;
selectedNode.Remove();
parent.Nodes.Insert(selectedIndex - 1, selectedNode);
treeViewChain.SelectedNode = selectedNode;
}
I'm trying to populate a treeview from a list of folder path, for example:
C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\AppPatch\MUI\040C
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409
with an ouput like this:
├───addins
├───AppPatch
│ └───MUI
│ └───040C
├───Microsoft.NET
│ └───Framework
│ └───v2.0.50727
│ └───MUI
│ └───0409
Notice there's no 'C:\WINDOWS\Microsoft.NET' or 'C:\WINDOWS\Microsoft.NET\Framework' in the list. I've been working on this for almost two days and there's a bunch of bug in my code. Hope I can get help from here.
Thanks.
Eric
private void Form1_Load(object sender, EventArgs e)
{
var paths = new List<string>
{
#"C:\WINDOWS\AppPatch\MUI\040C",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
#"C:\WINDOWS\addins",
#"C:\WINDOWS\AppPatch",
#"C:\WINDOWS\AppPatch\MUI",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
};
treeView1.PathSeparator = #"\";
PopulateTreeView(treeView1, paths, '\\');
}
private static void PopulateTreeView(TreeView treeView, IEnumerable<string> paths, char pathSeparator)
{
TreeNode lastNode = null;
string subPathAgg;
foreach (string path in paths)
{
subPathAgg = string.Empty;
foreach (string subPath in path.Split(pathSeparator))
{
subPathAgg += subPath + pathSeparator;
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
if (nodes.Length == 0)
if (lastNode == null)
lastNode = treeView.Nodes.Add(subPathAgg, subPath);
else
lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
else
lastNode = nodes[0];
}
}
}
for a linq'y version:
public static TreeNode MakeTreeFromPaths(List<string> paths, string rootNodeName = "", char separator = '/')
{
var rootNode = new TreeNode(rootNodeName);
foreach (var path in paths.Where(x => !string.IsNullOrEmpty(x.Trim()))) {
var currentNode = rootNode;
var pathItems = path.Split(separator);
foreach (var item in pathItems) {
var tmp = currentNode.Nodes.Cast<TreeNode>().Where(x => x.Text.Equals(item));
currentNode = tmp.Count() > 0 ? tmp.Single() : currentNode.Nodes.Add(item);
}
}
return rootNode;
}
ehosca answer is correcr, but there is a little problem,
when I change paths to like this
C:\WINDOWS\AppPatch\MUI\040C
D:\WIS\Microsoft.NET\Framework\v2.0.50727
E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409
It will popoulate treeview like this.
But adding some extra code we can avoid this situation. So I changed the code in PopulateTreeView
private static void PopulateTreeView(TreeView treeView, string[] paths, char pathSeparator)
{
TreeNode lastNode = null;
string subPathAgg;
foreach (string path in paths)
{
subPathAgg = string.Empty;
foreach (string subPath in path.Split(pathSeparator))
{
subPathAgg += subPath + pathSeparator;
TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
if (nodes.Length == 0)
if (lastNode == null)
lastNode = treeView.Nodes.Add(subPathAgg, subPath);
else
lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
else
lastNode = nodes[0];
}
lastNode = null; // This is the place code was changed
}
}
Now it works fine like this
I took your code, and it work very well,
but i made just a little modification for improving the load speed
when it is used whit a large list of files
it seems like find operation, and string operations generally are very slow
private TreeNode PopulateTreeNode2(string[] paths, string pathSeparator)
{
if (paths == null)
return null;
TreeNode thisnode = new TreeNode();
TreeNode currentnode;
char[] cachedpathseparator = pathSeparator.ToCharArray();
foreach (string path in paths) {
currentnode = thisnode;
foreach (string subPath in path.Split(cachedpathseparator))
{
if (null == currentnode.Nodes[subPath])
currentnode = currentnode.Nodes.Add(subPath, subPath);
else
currentnode = currentnode.Nodes[subPath];
}
}
return thisnode;
}
then you can use:
string[] paths = {
#"C:\WINDOWS\AppPatch\MUI\040C",
#"D:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
#"E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
#"C:\WINDOWS\addins",
#"C:\WINDOWS\AppPatch",
#"C:\WINDOWS\AppPatch\MUI",
#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
};
TreeView treeview = new TreeView();
treeview.Nodes.Add(PopulateTreeNode2(paths, "\\"));
NOTE: maybe some string sensitivity check will be needed in both solutions,
in order to prevent some folders re creations.
because some url could be pointing to the same folder on the disk
but spelled different such as:
Windows ; WinDOWs , WINDOWS
Here's some very old code I once used to create an ASP.NET treeview from code (assuming TreeView has an ID of TreeViewFolders):
protected void Page_Load(object sender, EventArgs e)
{
GenerateTreeView(#"C:\WINDOWS\");
}
private void GenerateTreeView(string rootPath)
{
GetFolders(System.IO.Path.GetFullPath(rootPath), TreeViewFolders.Nodes);
TreeViewFolders.ExpandDepth = 1;
}
// recursive method to load all folders and files into tree
private void GetFolders(string path, TreeNodeCollection nodes)
{
// add nodes for all directories (folders)
string[] dirs = Directory.GetDirectories(path);
foreach (string p in dirs)
{
string dp = p.Substring(path.Length);
nodes.Add(Node("", p.Substring(path.Length), "folder"));
}
// add nodes for all files in this directory (folder)
string[] files = Directory.GetFiles(path, "*.*");
foreach (string p in files)
{
nodes.Add(Node(p, p.Substring(path.Length), "file"));
}
// add all subdirectories for each directory (recursive)
for (int i = 0; i < nodes.Count; i++)
{
if (nodes[i].Value == "folder")
GetFolders(dirs[i] + "\\", nodes[i].ChildNodes);
}
}
// create a TreeNode from the specified path, text and type
private TreeNode Node(string path, string text, string type)
{
TreeNode n = new TreeNode();
n.Value = type;
n.Text = text;
return n;
}
private void Form2_Load(object sender, EventArgs e)
{
treeView1.CheckBoxes = true;
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = true;
}
string[] drives = Environment.GetLogicalDrives();
foreach (string drive in drives)
{
// treeView1.Nodes[0].Nodes[1].Checked = true;
DriveInfo di = new DriveInfo(drive);
int driveImage;
switch (di.DriveType)
{
case DriveType.CDRom:
driveImage = 3;
break;
case DriveType.Network:
driveImage = 6;
break;
case DriveType.NoRootDirectory:
driveImage = 8;
break;
case DriveType.Unknown:
driveImage = 8;
break;
default:
driveImage = 2;
break;
}
TreeNode node = new TreeNode(drive.Substring(0, 1), driveImage, driveImage);
node.Tag = drive;
if (di.IsReady == true)
node.Nodes.Add("...");
treeView1.Nodes.Add(node);
}
foreach (TreeNode node in treeView1.Nodes)
{
node.Checked = true;
}
}
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
{
if (e.Node.Nodes.Count > 0)
{
if (e.Node.Nodes[0].Text == "..." && e.Node.Nodes[0].Tag == null)
{
e.Node.Nodes.Clear();
string[] dirs = Directory.GetDirectories(e.Node.Tag.ToString());
foreach (string dir in dirs)
{
DirectoryInfo di = new DirectoryInfo(dir);
TreeNode node = new TreeNode(di.Name, 0, 1);
node.Checked = true;
try
{
node.Tag = dir;
if (di.GetDirectories().Count() > 0)
node.Nodes.Add(null, "...", 0, 0).Checked = node.Checked;
}
catch (UnauthorizedAccessException)
{
node.ImageIndex = 12;
node.SelectedImageIndex = 12;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "DirectoryLister", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
node.Checked = e.Node.Checked;
e.Node.Nodes.Add(node);
}
}
}
}
}
}
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
button1.Enabled = false;
TreeNode node = e.Node;
bool is_checked = node.Checked;
foreach (TreeNode childNode in e.Node.Nodes)
{
childNode.Checked = e.Node.Checked;
}
treeView1.SelectedNode = node;
}
I've managed to create a tree from path list using only for cycles. And it looks like it is the simpliest answer of this question at this moment.
Use this block of code to create a tree. list is the list of your files or folders, treeView1 is your TreeView.
//Creates a tree from given path list
foreach (string path in list)
{
TreeNodeCollection nodes = treeView1.Nodes;
foreach (string path_part in path.Split('\\'))
{
//Here it adds a new node (file or folder)
if (!nodes.ContainsKey(path_part))
nodes.Add(path_part, path_part);
//Go one node deeper
nodes = nodes[path_part].Nodes;
}
}
Note - this may break if you use it with paths that start with the path separator (e.g. /home/user)
And if you want to remove common parts of your paths (or remove single parent nodes), use this block of code right after the previous one:
//This removes "single" TreeNodes (common paths)
while (treeView1.Nodes.Count == 1)
{
//This "unpacks" child TreeNodes from the only parent TreeNode
for (int i = 0; i < treeView1.Nodes[0].Nodes.Count; i++)
treeView1.Nodes.Add(treeView1.Nodes[0].Nodes[i]);
//This removes parent TreeNode
treeView1.Nodes.RemoveAt(0);
}
This will generate an empty tree if all of your paths are the same.