I don't know how to show show all data in a treeview control:
here is my code:
private void PopulateTree(string path, int depth, TreeNode parent)
{
if (depth == 0)
{
//This make a child
parent.Nodes.Add(new TreeNode(path);
return;
}
//This makes a parent
TreeNode first = new TreeNode(path);
parent.Nodes.Add(first);
foreach (var v in ListWithPaths)
{
PopulateTree(v, depth - 1, first);
}
}
It only seems to works when depth=1
parent
-parent
--parent
---child
---child
--parent
---child
---child
-/parent
/parent
This is how I see it....
I have found this answer from here :
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];
}
}
}
foreach (var v in ListWithPaths)
{
PopulateTree(v, depth - 1, first);
}
}
Based on the path, it's creating the depth.
If this is not the wished behaviour, you can change the PopulateTreeView-Function accordingly.
There are some unclear moments in your code:
Do you want to explicitly restrict path depth (e.g. show paths up to 3d level only)
What is ListWithPaths? Can two paths have a common node?
To show a single path with restriction (depth) the code could be
private void PopulateTree(String path, TreeNode parent, int depth) {
if (depth == 0) // <- Artificial criterium
return;
if (String.IsNullOrEmpty(path))
return;
int index = path.IndexOf(Path.DirectorySeparatorChar);
String directoryName = (index < 0) ? path : path.Substring(0, index);
String otherName = (index < 0) ? null : path.Substring(index + 1);
TreeNode childNode = parent.Nodes.Add(directoryName);
PopulateTree(otherName, childNode, depth - 1);
}
In order to load a collection of paths without any restriction with possible common nodes you can use
something like this:
private void PopulateTree(String path, TreeView view, TreeNode parent) {
if (String.IsNullOrEmpty(path))
return;
int index = path.IndexOf(Path.DirectorySeparatorChar);
String directoryName = (index < 0) ? path : path.Substring(0, index);
String otherName = (index < 0) ? null : path.Substring(index + 1);
TreeNode childNode = null;
TreeNodeCollection nodes = (parent == null) ? view.Nodes : parent.Nodes;
foreach (TreeNode node in nodes)
if (String.Equals(node.Name, directoryName)) {
childNode = node;
break;
}
if (childNode == null)
childNode = nodes.Add(directoryName);
PopulateTree(otherName, view, childNode);
}
private void PopulateTree(IEnumerable<String> paths, TreeView view) {
view.BeginUpdate();
try {
foreach (String path in paths)
PopulateTree(path, view, null);
}
finally {
view.EndUpdate();
}
}
...
PopulateTree(ListWithPaths, MyTreeView)
Related
I have an Observable collection of Paths.
The thing I want to do is to update my treeView on collection changed.
Could you please help me with creating method that takes Treeview, FilePath and PathSeparator as parameters and adding new node to my treeView. This is what i have now:
private void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
TreeViewAddNode(TreeView,Path,PathSeparator)
}
TreeViewAddNode(TreeView treeView, string path, char pathSeparator)
{
foreach (string subPath in path.Split(pathSeparator))
{
//Hear should be logic to add new nodes if they don't exist }
}
}
As the Result I wanna have something like that:
C:
--Temp
----File1.txt
----File2.txt
----New Foledr
-------File3.txt
--AnotherFolder
----File4.txt
D:
--New Folder
----File.txt
EDIT
Now with better understanding on what is being asked:
private void TreeViewAddNode(TreeView treeView, string path, char pathSeparator)
{
string[] split = path.Split(pathSeparator);
for(int i = 0; i < split.Length; i++)
{
if(i == 0)
{
checkTreeView(treeView, split[0]);
}
else
{
TreeNode node = treeView1.Nodes.Find(split[i - 1], true)[0];
checkNodes(node, split[i]);
}
}
}
private void checkTreeView(TreeView treeView, string path)
{
bool exists = false;
foreach(TreeNode node in treeView.Nodes)
{
if(node.Text == path)
{
exists = true;
}
}
if(!exists)
{
TreeNode node = treeView.Nodes.Add(path);
node.Name = path;
}
}
private void checkNodes(TreeNode parent, string path)
{
bool exists = false;
foreach(TreeNode node in parent.Nodes)
{
if(node.Text == path)
{
exists = true;
}
}
if(!exists)
{
TreeNode node = parent.Nodes.Add(path);
node.Name = path;
}
}
checkTreeView checks if the path is allready present in the treeview nodes. if it isn't add it to the treeview. Same goes for checkNodes.
How do I print out a given node from my binary search tree using a method called PrintNodes.
Here is my Node class:
public class Node
{
public string data;
public Node left;
public Node right;
public Node(string data)
{
this.data = data;
}
}
And here is my Binary Search Tree Class:
class BinarySearchTree
{
public Node root, current;
public BinarySearchTree()
{
this.root = null;
}
public void AddNode(string a) // code to insert nodes to the binary search tree
{
Node newNode = new Node(a); //create a new node
if (root == null) // if the tree is empty new node will be the root node
root = newNode;
else
{
Node previous;
current = root;
while (current != null)
{
previous = current;
if (string.Compare(a, current.data) < 0) //if the new node is less than the current node
{
current = current.left;
if (current == null)
previous.left = newNode;
}
else //if the new node is greater than the current node
{
current = current.right;
if (current == null)
previous.right = newNode;
}
}
}
}
This is the what I have so far for my PrintNodes method, but I just realised that its not actually printing the given node its just printing the string that I pass into the method(I'm really new to this as you can see)
public String PrintNodes(string a)
{
string Output = "";
if (a != null)
{
Output += "Node: " + a;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
I know I have to somehow compare the string that is passed into the method to the node I am trying to print but I have no clue what to do my mind has gone blank.
Your Find method would look something like this:
public Node Find(key, root)
{
Node current-node = root;
while (current-node != null)
{
if (current-node.data == key)
return current-node;
else if (key < current-node.data)
current-node = current-node.left;
else
current-node = current-node.right;
}
return null;
}
Your PrintNodes method could then be:
public String PrintNodes(string a)
{
string Output = "";
Node theNode = Find(a);
if (Node != null)
{
Output += "Node: " + theNode.data;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
Cheers
EDIT: I assume that your Node object will have some other "payload" attached to it, as right now you're simply printing the search string if found :-)
I believe that you need to find some string in the tree and print it.
if it is
here is a pseudo code
public String PrintNodes(string a , Node root)
{
string Output = "";
if( a == null )
return "string is empty";
Node curent;
curent = root;
while( curent != null )
{
compVal = string.Compare(a, current.data)
if ( compVal < 0 )
{
//goto leftNode
curent = curent.left
}
else if ( compVal > 0 )
{
//goto rightNode
curent = curent.right
}
else
{
//this is it
break;
}
}
if curent == null
return "string not found";
else
return
curent.data;
}
I wrote the following code to iterate my Treeview and find the full path given.
I get the correct position and the listview also shows the correct content, but the treeview is not expanded. It seems that the .Expand() method does not firing.
What could that be about?
The Form with the Treeview is a Dialog, which is initialized once at the program-start and then is refreshed and shown when needed.
Because of the huge number of folders into the deep, I just load 2 levels of folders downward with each manually expanded.
Before I show the Dialog again, I set the SelectedPath to the full path which should be expanded and than calling the ExpandToPath method.
private void treeView1_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e) {
if(e.Node.Tag != null && e.Node.Nodes.Count > 0)
PopulateTreeView(e.Node, 1);
}
private void PopulateTreeView(TreeNode node, int depth) {
if(node.Tag != null) {
TreeViewTag tag = node.Tag as TreeViewTag;
if(tag.Visited && node.Nodes.Count > 0) {
foreach(TreeNode n in node.Nodes) {
if(depth <= 1)
PopulateTreeView(n, depth + 1);
}
} else {
TreeNode aNode;
try {
DirectoryInfo[] infos = tag.Info.GetDirectories();
foreach(DirectoryInfo subDir in infos) {
try {
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = new TreeViewTag() { Info = subDir, Visited = true };
aNode.ImageKey = "folderOpen";
if(depth <= 1)
PopulateTreeView(aNode, depth + 1);
node.Nodes.Add(aNode);
} catch(UnauthorizedAccessException ex11) {
} catch(Exception ex12) {
}
}
} catch(UnauthorizedAccessException ex1) {
} catch(Exception ex2) {
}
}
}
}
public void ExpandToPath(string path) {
currentNodeInfo = new DirectoryInfo(path);
TreeNode root = this.treeView1.Nodes[0];
if(path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path = path.Substring(0, path.Length - 1);
Stack<TreeNode> search = new Stack<TreeNode>();
search.Push(root);
while(search.Count > 0) {
TreeNode current = search.Pop();
string compare = (current.Tag as TreeViewTag).Info.FullName;
if(path.Equals(compare)) {
current.Expand();
PopulateListView((current.Tag as TreeViewTag).Info);
break;
} else {
if(path.StartsWith(compare)) {
current.Expand();
foreach(TreeNode node in current.Nodes) {
search.Push(node);
}
}
}
}
search.Clear();
search = null;
}
hi how i can set a image for my treeView nodes... I have a parent and a child node.
here is my code:
private void btnShowLicstate_Click(object sender, EventArgs e)
{
treeLic.Nodes.Clear();
string command = "\"C:\\lmxendutil.exe\" -licstatxml -host lwserv005 -port 6200";
string output = ExecuteCommand(command);
string final_output = output.Substring(90, output.Length - 90);
XmlReader xr = XmlReader.Create(new StringReader(final_output));
var xDoc = XDocument.Load(xr);
TreeNode root = new TreeNode();
LoadTree(xDoc.Root.Element("LICENSE_PATH"), root);
treeLic.Nodes.Add(root);
treeLic.ImageList = imageList1;
}
public void LoadTree(XElement root, TreeNode rootNode)
{
foreach (var e in root.Elements().Where(e => e.Attribute("NAME") != null))
{
var node = new TreeNode(e.Attribute("NAME").Value);
rootNode.Nodes.Add(node);
if (e.Name == "FEATURE")
{
node.SelectedImageIndex = 1;
}
else if (e.Name == "USER")
{
node.SelectedImageIndex = 0;
}
LoadTree(e, node);
}
}
my problem is that i have everyone the same picture but i want for FEATURE the index 1 and for USER the Index 2 but why it don't work ? :(
You should use ImageIndex property instead of SelectedImageIndex.
The first one is the index from ImageList for node in unselected state and the second one is applied when you select node using mouse, keyboard or through code.
Like this:
TreeNode[] treeNodes = treeView.Nodes.Find(searchString, true);
but I want it to search in the text field instead of the name field.
I am not aware of any inbuilt method but you may use LINQ
TreeNode[] treeNodes = treeView.Nodes
.Cast<TreeNode>()
.Where(r => r.Text == "yourText")
.ToArray();
To search all tree nodes (not only the direct child nodes) you can use the extension method below
var nodes = treeView1.FlattenTree()
.Where(n => n.Text == "sometext")
.ToList();
--
public static class SOExtension
{
public static IEnumerable<TreeNode> FlattenTree(this TreeView tv)
{
return FlattenTree(tv.Nodes);
}
public static IEnumerable<TreeNode> FlattenTree(this TreeNodeCollection coll)
{
return coll.Cast<TreeNode>()
.Concat(coll.Cast<TreeNode>()
.SelectMany(x => FlattenTree(x.Nodes)));
}
}
If I understand you correctly (you last question was very confusing), you can write a find method yourself as follows
public static TreeNode[] Find(this TreeNode motherNode, string findNodeText)
{
List<TreeNode> nodeList = new List<TreeNode>();
foreach (TreeNode childNode in motherNode.Nodes)
if (childNode.Text.Equals(findNodeText, StringComparison.CurrentCulture))
nodeList.Add(childNode);
return nodeList.ToArray<TreeNode>();
}
This method can be used like
TreeView myTreeView = new TreeView();
foreach (TreeNode node in myTreeView.Nodes)
{
TreeNode[] childNodes = node.Find("Text");
// Do something...
}
I hope this helps.
The following code only shows the nodes which matches the search criteria.
Copy the following code in the search event
private void tbxSearch_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
trvMenu.BeginUpdate();
if (tbxSearch.Text.Length > 0)
{
for (int i = trvMenu.Nodes.Count; i > 0 ; i--)
{
NodeFiltering(trvMenu.Nodes[i - 1], tbxSearch.Text);
}
}
trvMenu.EndUpdate();
}
Then create the serch & filter function
private bool NodeFiltering(TreeNode Nodo,string Texto)
{
bool resultado = false;
if (Nodo.Nodes.Count == 0)
{
if (Nodo.Text.ToUpper().Contains(Texto.ToUpper()))
{
resultado = true;
}
else
{
Nodo.Remove();
}
}
else
{
for (int i = Nodo.Nodes.Count; i > 0; i--)
{
if (NodeFiltering(Nodo.Nodes[i - 1], Texto))
resultado = true;
}
if (!resultado)
Nodo.Remove();
}
return resultado;
}
This code is pretty nice for creating Treeview menus with many levels.