I have four lists that I am trying to get the contents to show up in a TreeView on my Form.
My current problem is that only the last item in each list is showing up in the view.
I am sure it has something to do with how I am iterating through the list but I am pretty stuck on how to get each individual list item to show up in the tree.
My tree structure is:
Dog
Husky
huskylist
Chiwawa
chiwawlist
Cat
Siamese
siameselist
Tabby
tabbylist
My code for the Form where the tree view is:
public partial class Form1 : Form
{
private Model m_modelObj;
public Form1(Model modelObj)
{
InitializeComponent();
m_modelObj = modelObj;
List<Tabby> tabbyList = m_modelObj.TabbyList;
List<Siamese> siameseList = m_modelObj.SiameseList;
List<Husky> huskyList = m_modelObj.HuskyList;
List<Chiwawa> chiwawaList = m_modelObj.ChiwawaList;
//tree code
//add husky list
TreeNode node8 = null;
foreach (var item in huskyList)
{
node8 = new TreeNode(item.name);
}
TreeNode[] husky = new TreeNode[] { node8 };
//add chiwawa list
TreeNode node9 = null;
foreach (var item in chiwawaList)
{
node9 = new TreeNode(item.name);
}
TreeNode[] chiwawa = new TreeNode[] { node9 };
//dog breed
TreeNode node2 = new TreeNode("Husky", husky);
TreeNode node3 = new TreeNode("Chiwawa", chiwawa);
TreeNode[] dog = new TreeNode[] { node2, node3 };
//dog parent
TreeNode treeNode = new TreeNode("Dogs", dog);
treeView1.Nodes.Add(treeNode);
//add tabby list
TreeNode nodes = null;
foreach (var item in tabbyList)
{
nodes = new TreeNode(item.name);
}
TreeNode[] tabby = new TreeNode[] { nodes };
//add siamese list
TreeNode node7 = null;
foreach (var item in siameseList)
{
node7 = new TreeNode(item.name);
}
TreeNode[] siamese = new TreeNode[] { node7 };
//cat breed
TreeNode node4 = new TreeNode("Siamese", siamese);
TreeNode node5 = new TreeNode("Tabby", tabby);
TreeNode[] cat = new TreeNode[] { node4, node5 };
//cat parent
treeNode = new TreeNode("Cats", cat);
treeView1.Nodes.Add(treeNode);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void addDetailsBtn_Click(object sender, EventArgs e)
{
string animalType = comboBoxAnimalType.SelectedItem.ToString();
this.Hide();
PetInfoForm aPetInfoForm = new PetInfoForm(animalType, m_modelObj);
aPetInfoForm.Closed += (s, args) => this.Close();
aPetInfoForm.Show();
}
}
Create Object and Dynamic array in c# Refer here
TreeView Basic to understand Refer here
when you are creating the sub nodes you are overwrite the instance. you should maintain the nodes in a array.
//tree code
//add husky list
List<TreeNode> node8 = new List<TreeNode>();
foreach (var item in huskyList)
{
node8.Add(new TreeNode(item.name));
}
TreeNode[] husky = node8.ToArray();
//add chiwawa list
List<TreeNode> node9 = new List<TreeNode>();
foreach (var item in chiwawaList)
{
node9.Add(new TreeNode(item.name));
}
TreeNode[] chiwawa = node9.ToArray();
//dog breed
TreeNode node2 = new TreeNode("Husky", husky);
TreeNode node3 = new TreeNode("Chiwawa", chiwawa);
TreeNode[] dog = new TreeNode[] { node2, node3 };
//dog parent
TreeNode treeNode = new TreeNode("Dogs", dog);
treeView1.Nodes.Add(treeNode);
//add tabby list
List<TreeNode> nodes = new List<TreeNode>();
foreach (var item in tabbyList)
{
nodes.Add(new TreeNode(item.name));
}
TreeNode[] tabby =nodes.ToArray();
//add siamese list
List<TreeNode> node7 = new List<TreeNode>();
foreach (var item in siameseList)
{
node7.Add(new TreeNode(item.name));
}
TreeNode[] siamese = node7.ToArray();
//cat breed
TreeNode node4 = new TreeNode("Siamese", siamese);
TreeNode node5 = new TreeNode("Tabby", tabby);
TreeNode[] cat = new TreeNode[] { node4, node5 };
//cat parent
treeNode = new TreeNode("Cats", cat);
treeView1.Nodes.Add(treeNode);
Or
Using LINQ you can create the tree like this
// Code Using Linq
TreeNode husky = new TreeNode("Husky", huskyList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode chiwawa = new TreeNode("Chiwawa", chiwawaList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode Siamese = new TreeNode("Siamese", siameseList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode Tabby = new TreeNode("Tabby", tabbyList.Select(x => new TreeNode(x.name)).ToArray());
//parent nodes
treeView1.Nodes.AddRange(new[] {
new TreeNode("Dog", new TreeNode[] { husky, chiwawa }),
new TreeNode("Cat", new TreeNode[] { Siamese, Tabby })
});
Related
I have the code below to expand the tree node to add childeren to its parents , till the nth level.
Issue : The child is added to the first level always, instead it should have been added till the nth level, to its appropriate parent.
Code below:
public void Populate_Node(Object sender, TreeNodeEventArgs e)
{
// Authenticating
TreeProvider cmsTree = new TreeProvider(MembershipContext.AuthenticatedUser);
//selecting the expanding node
var node = cmsTree.SelectSingleNode(SiteContext.CurrentSiteName, "/Level1-2ndItem", "en-US");
CMS.DocumentEngine.TreeNodeCollection myChildren = node.AllChildren;
//Making array of child treenodes of selected node
IEnumerable<CMS.DocumentEngine.TreeNode> TreeNodes = myChildren.AsEnumerable<CMS.DocumentEngine.TreeNode>();
foreach (var tree in myChildren)
{
System.Web.UI.WebControls.TreeNode ParenTreeNode = new System.Web.UI.WebControls.TreeNode();
ParenTreeNode.Text = tree.NodeID.ToString() + ". " + SiteContext.CurrentSiteName;
ParenTreeNode.Value = tree.NodeID.ToString();
AddExpandedNodes(ParenTreeNode);
}
}
private void AddExpandedNodes(System.Web.UI.WebControls.TreeNode TreeNode)
{
CMS.DocumentEngine.TreeProvider cmsTree = new CMS.DocumentEngine.TreeProvider(CMS.Membership.MembershipContext.AuthenticatedUser);
var node = cmsTree.SelectSingleNode(CMS.SiteProvider.SiteContext.CurrentSiteName, "/", "en-US");
CMS.DocumentEngine.TreeNodeCollection myChildren = node.AllChildren;
IEnumerable<CMS.DocumentEngine.TreeNode> childTreeNodes = myChildren.AsEnumerable<CMS.DocumentEngine.TreeNode>().Where(x => x.NodeParentID == Convert.ToInt32(TreeNode.Value));
foreach (var childTree in childTreeNodes)
{
System.Web.UI.WebControls.TreeNode ChildNode = new System.Web.UI.WebControls.TreeNode();
ChildNode.Text = childTree.NodeID.ToString() + ". " + childTree.DocumentName.ToString();
ChildNode.Value = childTree.NodeID.ToString();
ChildNode.ChildNodes.Add(ChildNode);
AddExpandedNodes(ChildNode);
tvContentTree.Nodes.Add(ChildNode);
}
}
i am new with Nodes here.. :) i came up with this algorithm but it only shows the list of parent nodes.. like this..
a
a.txt
b
c
c
m
n
b
o
p
etc...
i want the next node will be put in one of the node inside the previous node.. so it will come up like this..
a
a.txt
b
o
p
c
m
n
etc...
i have some ideas in mind but i can implement it to codes.. :) any help please..
private void ListDirectory(TreeView treeView, String path)
{
Stack<string> stack = new Stack<string>();
TreeNode DirFilesCollection = new TreeNode();
stack.Push(path);
while (stack.Count > 0)
{
string dir = stack.Pop();
try
{
List<String> parentDir = new List<string>();
parentDir.AddRange(Directory.GetFiles(dir, "*.*"));
parentDir.AddRange(Directory.GetDirectories(dir));
DirectoryInfo d = new DirectoryInfo(dir);
TreeNode TParent = new TreeNode(d.Name);
foreach (String s in parentDir)
{
FileInfo f = new FileInfo(s);
TreeNode subItems = new TreeNode(f.Name);
TParent.Nodes.Add(subItems);
}
DirFilesCollection.Nodes.Add(TParent);
foreach (string dn in Directory.GetDirectories(dir))
{
stack.Push(dn);
}
}
catch
{}
}
Action clearTreeView = () => treeView.Nodes.Clear();
this.Invoke(clearTreeView);
Action showTreeView = () => treeView.Nodes.Add(DirFilesCollection);
this.Invoke(showTreeView);
}
Option #1: Recursive approach:
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
foreach (var file in directoryInfo.GetFiles())
directoryNode.Nodes.Add(new TreeNode(file.Name));
return directoryNode;
}
Option #2: Non-recursive approach:
private static void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var stack = new Stack<TreeNode>();
var rootDirectory = new DirectoryInfo(path);
var node = new TreeNode(rootDirectory.Name) { Tag = rootDirectory };
stack.Push(node);
while (stack.Count > 0)
{
var currentNode = stack.Pop();
var directoryInfo = (DirectoryInfo)currentNode.Tag;
foreach (var directory in directoryInfo.GetDirectories())
{
var childDirectoryNode = new TreeNode(directory.Name) { Tag = directory };
currentNode.Nodes.Add(childDirectoryNode);
stack.Push(childDirectoryNode);
}
foreach (var file in directoryInfo.GetFiles())
currentNode.Nodes.Add(new TreeNode(file.Name));
}
treeView.Nodes.Add(node);
}
By the beginning of this week Iwas having a problem with TreeView not displaying children. Everything got worked out through recursiveness. However, a new and unexpected problem arose: the methods i'm using are getting duplicate nodes on some specific DataTables.
Having this DataTable of two columns:
ParentOT ChildOT
20120601 20120602
20120601 20120603
20120601 20120604
20120601 20120611
20120601 20120612
20120602 20120605
20120602 20120606
20120602 20120607
20120602 20120608
20120602 20120610
20120603 20120607
20120603 20120608
20120603 20120609
If I try to display its Treeview I get the right treeview, but five times consecutively (the times the parent appears as parent in parentOT records).
The Methods are these:
private TreeView cargarOtPadres(TreeView trv, int otPadre, DataTable datos)
{
if (datos.Rows.Count > 0)
{
foreach (DataRow dr in datos.Select("OTPadre="+ otPadre))
{
TreeNode nodoPadre = new TreeNode();
nodoPadre.Text = dr["OTPadre"].ToString();
trv.Nodes.Add(nodoPadre);
cargarSubOts(ref nodoPadre, int.Parse(dr["OTPadre"].ToString()), datos);
}
}
return trv;
}
private void cargarSubOts(ref TreeNode nodoPadre, int otPadre, DataTable datos)
{
DataRow[] otHijas = datos.Select("OTPadre=" + otPadre);
foreach (DataRow drow in otHijas)
{
TreeNode hija = new TreeNode();
hija.Text = drow["OTHija"].ToString();
nodoPadre.Nodes.Add(hija);
cargarSubOts(ref hija, int.Parse(drow["OTHija"].ToString()), datos);
}
}
With Tables with just 1 great parent appearing 1 time only, it works great. How can i prevent the TreeView from duplicating??
I'll leave the answer for the sake of completion. This solution came courtesy of #King King
public static class TreeViewExtension
{
public static void LoadFromDataTable(this TreeView tv, DataTable dt)
{
var parentNodes = dt.AsEnumerable()
.GroupBy(row => (string)row[0])
.ToDictionary(g => g.Key, value => value.Select(x => (string)x[1]));
Stack<KeyValuePair<TreeNode, IEnumerable<string>>> lookIn = new Stack<KeyValuePair<TreeNode, IEnumerable<string>>>();
HashSet<string> removedKeys = new HashSet<string>();
foreach (var node in parentNodes)
{
if (removedKeys.Contains(node.Key)) continue;
TreeNode tNode = new TreeNode(node.Key);
lookIn.Push(new KeyValuePair<TreeNode, IEnumerable<string>>(tNode, node.Value));
while (lookIn.Count > 0)
{
var nodes = lookIn.Pop();
foreach (var n in nodes.Value)
{
IEnumerable<string> children;
TreeNode childNode = new TreeNode(n);
nodes.Key.Nodes.Add(childNode);
if (parentNodes.TryGetValue(n, out children))
{
lookIn.Push(new KeyValuePair<TreeNode, IEnumerable<string>>(childNode, children));
removedKeys.Add(n);
}
}
}
tv.Nodes.Add(tNode);
}
}
}
You create this class
And you use afterwards like this.
treeView1.LoadFromDataTable(DataTable);
Be sure to use it with a String type DataTable. If you have a int type Table, you can do something like this:
DataTable stringDataTable = intDataTable.Clone();
stringDataTable.Columns[0].DataType = typeof(string);
stringDataTable.Columns[1].DataType = typeof(string);
foreach (DataRow dr in intDataTable.Rows)
{
stringDataTable.ImportRow(dr);
}
treeView1.LoadFromDataTable(stringDataTable);
I have a table in this structure
ListA labelName
1 Colorado
1 Wyoming
1 Illinois
2 New York
2 Ohio
I am trying to create a tree where if LISTA = 1, it goes under one node called "header one" and Colorado, Wyoming, Illinois as its Leaf and samething with value "2"... by doing this I am getting 3 "Header one" nodes instead of having all those three nodes under one...
SqlCommand cmd = con.CreateCommand();
comd.CommandText = "SELECT * FROM myTable";
con.Open();
SqlDataReader reader = comd.ExecuteReader();
while (reader.Read())
{
City MyData = new City();
MyData.ListA = reader["ListA"].ToString().Trim();
MyData.labelName = reader["labelName"].ToString().Trim();
giveData.Add(MyData);
}
int count = 1;
List<TreeNode> myNode = new List<TreeNode>();
foreach (City MyData in giveData)
{
// 1st foreach
if (MyData.ListA != "1")
{
TreeNode treeNode = new TreeNode();
treeNode.id = count++;
treeNode.name = "Header One";
treeNode.leaf = false;
List<TreeNode> Level1 = new List<TreeNode>();
foreach (City labelName in giveData)
{
if (labelName.ListA == "1")
{// 2nd foreach
TreeNode node1 = new TreeNode();
node1.id = count++;
node1.name = labelName.labelName;
node1.leaf = true;
Level1.Add(node1);
}
}
treeNode.children = Level1;
myNode.Add(treeNode);
}
else if (MyData.ListA != "2")
{
TreeNode treeNode = new TreeNode();
treeNode.id = count++;
treeNode.name = "Header Two";
treeNode.leaf = false;
List<TreeNode> Level1 = new List<TreeNode>();
foreach (City labelName in giveData)
{
if (labelName.ListA == "2")
{// 2nd foreach
TreeNode node1 = new TreeNode();
node1.id = count++;
node1.name = labelName.labelName;
node1.leaf = true;
Level1.Add(node1);
}
}
treeNode.children = Level1;
myNode.Add(treeNode);
}
}
return JsonConvert.SerializeObject(myNode);
What would be the best way to handle this
What you need to do is group the data on ListA.
var groups = giveData.GroupBy(state => state.ListA);
foreach(var group in groups)
{
//add header to treeview
string header = group.Key;
foreach(var state in group)
{
//add this state as a child of the group you just added
}
}
I'd also suggest creating a lookup to help you map the ListA number to it's textual representation:
var headerLookup = new Dictionary<string, string>()
{
{"1", "Header One"},
{"2", "Header Two"},
{"3", "Header Three"}
};
This will allow you to do the following:
string headerText = headerLookup[group.Key];
I have to develop a web part for SharePoint that reads a list and creates a tree view.
The tree view has to be organized as follows:
The root (or roots) is to be created by a choice field which represents a category, for instance Drinks,
the child nodes are the name of the rows that contain that category, the tree view has to be created programmatically.
List:
Title(string) Category(Choice)
Coke Drinks
Beer Drinks
Fish Food
Chips Food
Would produce this:
Drinks
Coke
Beer
Food
Fish
Chips
code I have so far
TreeView treeView;
TreeNode rootNode;
TreeNode childNode;
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
// render the control
base.RenderContents(writer);
}
protected override void CreateChildControls()
{
List<TreeNode> items = new List<TreeNode>();
base.CreateChildControls();
// get the current site
using (SPSite Site = new SPSite(SPContext.Current.Site.Url + "/UberWiki"))
{
using (SPWeb currentWeb = Site.OpenWeb())
{
// set the tree view properties
SPList list = currentWeb.Lists["Pages"];
SPFieldChoice field = (SPFieldChoice)list.Fields["Categories"];
foreach (string str in field.Choices)
{
treeView = new System.Web.UI.WebControls.TreeView();
rootNode = new System.Web.UI.WebControls.TreeNode(str);
treeView.Nodes.Add(rootNode);
foreach (SPListItem rows in list.Items)
{
childNode = new System.Web.UI.WebControls.TreeNode(rows.Title);
treeView.Nodes.Add(childNode);
}
}
}
this.Controls.Add(treeView);
base.CreateChildControls();
}
}
Found the solution:
using (SPSite Site = new SPSite(SPContext.Current.Site.Url + "/UberWiki"))
{
using (SPWeb currentWeb = Site.OpenWeb())
{
SPList list = currentWeb.Lists["Pages"];
SPFieldChoice field = (SPFieldChoice)list.Fields["Categories"];
treeView = new System.Web.UI.WebControls.TreeView();
foreach (string str in field.Choices)
{
treeNode = new System.Web.UI.WebControls.TreeNode(str);
foreach (SPListItem rows in list.Items)
{
SPFieldMultiChoiceValue multiChoice = new SPFieldMultiChoiceValue(Convert.ToString(rows["Wiki Categories"]));
string input = multiChoice.ToString();
//remove the ;# that comes with the multiple choiches
string cleanString = input.Replace(";#", "");
if (cleanString == str)
{
string PageNameWithExt = rows.Name;
childNode = new System.Web.UI.WebControls.TreeNode(PageNameWithExt);
treeNode.ChildNodes.Add(childNode);
}
}
treeView.Nodes.Add(treeNode);
}
}
}
this.Controls.Add(treeView);
base.CreateChildControls();
}
Another solution without the need to clean the multi choice string values
using (SPSite Site = new SPSite(SPContext.Current.Site.Url + "/UberWiki"))
{
using (SPWeb currentWeb = Site.OpenWeb())
{
// set the tree view properties
SPList list = currentWeb.GetList(currentWeb.Url+"/Lists/Pages");
SPFieldChoice field = (SPFieldChoice)list.Fields["Categories"];
treeView = new System.Web.UI.WebControls.TreeView();
// Add root nodes
foreach (string str in field.Choices)
{
rootNode = new System.Web.UI.WebControls.TreeNode(str);
treeView.Nodes.Add(rootNode);
}
// Add child nodes
foreach (SPListItem rows in list.Items)
{
childNode = new System.Web.UI.WebControls.TreeNode(rows["Title"].ToString());
treeView.FindNode(rows["Categories"].ToString()).ChildNodes.Add(childNode);
}
}
this.Controls.Add(treeView);
base.CreateChildControls();
}