I am applying a datasource to a sublayout and obtaining the values of its children as follows:
Sitecore.Collections.ChildList childItems;
if (Sitecore.Context.Database.GetItem(this.DataSource) != null)
{
childItems = Sitecore.Context.Database.GetItem(this.DataSource).GetChildren();
}
else
{
litDataSourceError.Text += "You need to set a datasource";
}
foreach (Item item in childItems)
{
litDataSourceError.Text += "<h2>" + item.Fields["Title"].Value + "</h2>";
}
This is working as expected however these items also have children which I would like to output.
So my question is how to look down a further node within my ForEach to obtain the Childrens Children - there will only be these 2 levels of structure.
You should do the same as you did for your datasource (fetch the children of the Sitecore Item):
foreach (Item item in childItems)
{
litDataSourceError.Text += "<h2>" + item.Fields["Title"].Value + "</h2>";
foreach (Item child in item.GetChildren())
{
...
}
}
Related
I have an application that allows users to add new items into a TreeView control. When an item is selected the parent node reveals its child nodes, but it collapses when a new item (Button is clicked) is added to the Treeview control. I want it to stay expanded until the user interacts with it again.
//List<> collection is initialized
//Public class property is created to set it's member variables to the control values that the user enters
private void addButton_Click(object sender, EventArgs e)
{
if (ComboBoxOne.SelectedIndex != 0)
{
//Method that adds new item to a List<> Collection
AddToList();
//Method that goes through the List<> Collection, modifies the display of the item and adds it to the TreeView control
AddToTreeView();
}
}
//How I am adding the List<> objects to the treeview control
private void TravelTreeView()
{
TreeView1.Nodes.Clear();
//Items is the class I created and ObjectList is the List<>
foreach (Items obj in ObjectList)
{
TreeNode node = new TreeNode();
node.Text = obj.Name;
//Imagelist has 7 images
node.SelectedImageIndex = 0;
node.ImageIndex = obj.NameImage;
node.Nodes.Add(obj.AgeImage, "Age: " + obj.Age, 5);
node.Nodes.Add(obj.ZodiacImage, "Zodiac: " + obj.Zodiac, 6);
node.Nodes.Add(obj.JobImage, "Job: " + obj.Job, 7);
TreeView1.Nodes.Add(node);
}
}
I see that TreeView is cleared and then populated with list of nodes. As mentioned in the comment(s) you may check for IsExpanded property and then decide to call Expand on TreeNode.
Another way: As you are adding many new TreeNodes I would assume there is no previous state for these nodes to check for IsExpanded, in such a case, you may try something like below, the new Node is added in expanded state. Note Beginupdate/EndUpdate calls.
private void TravelTreeView()
{
// better to do this to avoid too many repaints
TreeView1.BeginUpdate();
TreeView1.Nodes.Clear();
//Items is the class I created and ObjectList is the List<>
foreach (Items obj in ObjectList)
{
TreeNode node = new TreeNode();
node.Text = obj.Name;
//Imagelist has 7 images
node.SelectedImageIndex = 0;
node.ImageIndex = obj.NameImage;
node.Nodes.Add(obj.AgeImage, "Age: " + obj.Age, 5);
node.Nodes.Add(obj.ZodiacImage, "Zodiac: " + obj.Zodiac, 6);
node.Nodes.Add(obj.JobImage, "Job: " + obj.Job, 7);
// add an expanded Node
node.Expand();
TreeView1.Nodes.Add(node);
}
// we are done with the updates to TreeView
TreeView1.EndUpdate();
}
WinForms does retain the state of the controls. The issue here seems to be the fact that you clean the items and then iterate your object and then reload the TreeView. In this case the items would be collapsed which is the default.
I would suggest the below approach,
private void TravelTreeView()
{
//Items is the class I created and ObjectList is the List<>
foreach (Items obj in ObjectList)
{
//Check to see if the item already exists
if (!TreeView1.Nodes.ContainsKey(obj.Name))
{
var node = new TreeNode();
node.Text = obj.Name;
//Imagelist has 7 images
node.SelectedImageIndex = 0;
node.ImageIndex = obj.NameImage;
node.Nodes.Add(obj.AgeImage, "Age: " + obj.Age, 5);
node.Nodes.Add(obj.ZodiacImage, "Zodiac: " + obj.Zodiac, 6);
node.Nodes.Add(obj.JobImage, "Job: " + obj.Job, 7);
TreeView1.Nodes.Add(node);
}
}
}
Information on the ContainsKey Method on TreeNodeCollection
i got this loop here:
foreach (object obje in this.treeViewSL.Items)
{
TreeViewItem TVI = (TreeViewItem)treeViewSL.ItemContainerGenerator.ContainerFromItem(obje);
if ((TVI.Header.ToString() == _object.NodeText))
{
TVI.IsSelected = true;
TVI.IsExpanded = true;
_selectedItem = treeViewSL.SelectedItem as TreeViewItem;
continue;
}
}
this works fine to look if there is treeviewitem with this header in the first items, but it seems that treeviewsl.Items doesn't count the childs, it gives me 1 back but there are 3, so 1 root with 2 childs, how i can loop through these also?
I have a requirement to bind folders and files to the treeview based on table data from data base, i tried lot of solution but failed to meet specific requirement.
Here is what im looking
Top folders
I have found one sample code and tried to achieve this
`
private void PopulateTreeview(DataTable dtFolders)
{
tvVendors.Nodes.Clear();
HierarchyTrees hierarchyTrees = new HierarchyTrees();
HierarchyTrees.HTree objHTree = null;
if (dtFolders.Rows.Count > 0)
{
foreach (DataRow dr in dtFolders.Rows)
{
objHTree = new HierarchyTrees.HTree();
objHTree.LevelDepth = int.Parse(dr["level"].ToString());
objHTree.NodeID = int.Parse(dr["folderid"].ToString());
objHTree.UnderParent = int.Parse(dr["parentid"].ToString());
objHTree.FIleName=dr["filename"].ToString();
objHTree.FilePath=dr["filepath"].ToString();
hierarchyTrees.Add(objHTree);
}
}
//Iterate through Collections.
foreach (HierarchyTrees.HTree hTree in hierarchyTrees)
{
//Filter the collection HierarchyTrees based on
//Iteration as per object Htree Parent ID
HierarchyTrees.HTree parentNode = hierarchyTrees.Find
(delegate(HierarchyTrees.HTree vendor)
{ return vendor.NodeID == hTree.UnderParent; });
//If parent node has child then populate the leaf node.
if (parentNode != null)
{
foreach (TreeNode tn in tvVendors.Nodes)
{
//If single child then match Node ID with Parent ID
if (tn.Value == parentNode.NodeID.ToString())
{
tn.ChildNodes.Add(new TreeNode
(hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
}
//If Node has multiple child ,
//recursively traverse through end child or leaf node.
if (tn.ChildNodes.Count > 0)
{
foreach (TreeNode ctn in tn.ChildNodes)
{
RecursiveChild(ctn, parentNode.NodeID.ToString(), hTree);
}
}
}
}
//Else add all Node at first level
else
{
tvVendors.Nodes.Add(new TreeNode
(hTree.NodeDescription, hTree.NodeID.ToString()));
}
}
tvVendors.ExpandAll();
}
public void RecursiveChild(TreeNode tn, string searchValue, HierarchyTrees.HTree hTree)
{
if (tn.Value == searchValue)
{
tn.ChildNodes.Add(new TreeNode
(hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
}
if (tn.ChildNodes.Count > 0)
{
foreach (TreeNode ctn in tn.ChildNodes)
{
RecursiveChild(ctn, searchValue, hTree);
}
}
}
Problem: I'm not able to bind file name to leaf node, if folder does not have any subfolder. bind the files. or if folder has subfolder and file both.bind both at same level. if folder is empty, it has nothing just bind it blank.
Could please test the code provide some solution`
foreach (TreeNode childnode in GetChildFolderNode(dataRow[ID].ToString(), table))
{
//Bind all folders
}
foreach (TreeNode childnode in GetChildFileNode(dataRow[ID].ToString(), table))
{
//bind all files
}
I have a method in which I have to populate dropdownlist from a collection that is formed like a tree. I have list of parent Objects, every parent can have list of child Objects, every child can have list of grandchild Objects and so on.
I have to loop through tha collection because I want to indent items so hierarchy is built.
ddl should look like this:(- is symbol for indent)
parent
-child
--grandchild
---grandgrandchild
-child
parent
..and so on..
How should I go about changing this method so i dont have loop inside a loop inside a loop, asume I dont know the depht of a tree
Thanks in advance!
Method:
private void BindObjectDropDown()
{
ddlObject.Items.Clear();
ObjectCollection collection = Object.GetList();
if (collection != null && collection.Count > 0)
{
foreach (var parent in collection)
{
ddlObject.Items.Add(new ListItem($"{parent.Title}", parent.Id.ToString()));
if (parent.Objects != null && parent.Objects.Count > 0)
{
foreach (var child in parent.Objects)
{
ddlObject.Items.Add(new ListItem($"{_ddlIndent}{child.Title}", child.Id.ToString()));
if (child.Objects != null && child.Objects.Count > 0)
{
foreach (var grandchild in child.Objects)
{
ddlObject.Items.Add(new ListItem($"{_ddlIndent}{_ddlIndent}{grandchild.Title}", grandchild.Id.ToString()));
//and so on and so on ....
}
}
}
}
}
foreach (ListItem item in ddlObject.Items)
{
item.Text = HttpUtility.HtmlDecode(item.Text);
}
}
}
If someone wants a solution, recursion, of course:
private void BindMyObjectDropDown()
{
ddlMyObject.Items.Clear();
MyObjectCollection collection = MyObject.GetList(0, true);
if (collection != null && collection.Count > 0)
{
AddDdlItems(collection, 0);
foreach (ListItem item in ddlMyObject.Items)
{
item.Text = HttpUtility.HtmlDecode(item.Text);
}
}
ddlMyObject.Items.Insert(0, new ListItem(EntityResource.DefaultDropDownPick, "0"));
}
private void AddDdlItems(MyObjectCollection collection, int depth)
{
string indent = string.Empty;
for (int i = 0; i < depth; i++)
{
indent += _ddlIndent;
}
foreach (var myObject in collection)
{
ddlMyObject.Items.Add(new ListItem($"{indent}{myObject.Title}", myObject.Id.ToString()));
if (myObject.Objects!= null && myObject.Objects.Count > 0)
{
AddDdlItems(myObject.Objects, depth + 1);
}
}
}
I really can't get out of this one.
I got treeview items in treeviews. The treeview items contain checkboxes with content. How do i get the content and put it in a list.
currently i got this
foreach (TreeViewItem item in treeView1.Items)
{
foreach (TreeViewItem childItem in item.Items)
{
CheckBox checkBoxTemp = childItem.Header as CheckBox;
if (checkBoxTemp == null) continue;
optieListBox.Items.Add(checkBoxTemp.Content);
}
}
I am not sure if i get your question correctly, but you can try this.
foreach (TreeViewItem childItem in item.Items)
{
CheckBox cbx = null;
//finds first checkbox
foreach(object child in childItem.Items){
cbx = child as CheckBox;
if (cbx != null) break;
}
ctrList.Items.Add(cbx.Content);
}
Bind your TreeView to a collection instead. That way you won't have to manipulate UI components to access the data, you will access the data directly.
The other way to do this is through recursion: Declare optieListBox list at class level and call GetContainers() method as an entry point call. optieListBox list should give you content list for all checked items in treeview.
List<string> optieListBox = new List<string>();
private List<TreeViewItem> GetAllItemContainers(TreeViewItem itemsControl)
{
List<TreeViewItem> allItems = new List<TreeViewItem>();
for (int i = 0; i < itemsControl.Items.Count; i++)
{
// try to get the item Container
TreeViewItem childItemContainer = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
// the item container maybe null if it is still not generated from the runtime
if (childItemContainer != null)
{
allItems.Add(childItemContainer);
List<TreeViewItem> childItems = GetAllItemContainers(childItemContainer);
foreach (TreeViewItem childItem in childItems)
{
CheckBox checkBoxTemp = childItem.Header as CheckBox;
if (checkBoxTemp != null)
optieListBox.Items.Add(checkBoxTemp.Content);
allItems.Add(childItem);
}
}
}
return allItems;
}
private void GetContainers()
{
// gets all nodes from the TreeView
List<TreeViewItem> allTreeContainers = GetAllItemContainers(this.objTreeView);
// gets all nodes (recursively) for the first node
TreeViewItem firstNode = this.objTreeView.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
if (firstNode != null)
{
List<TreeViewItem> firstNodeContainers = GetAllItemContainers(firstNode);
}
}
Try this:
List<string> values = new List<string>;
foreach (string node in treeView.Nodes)
{
values.Add(node);
}
//Loop through nodes
Also, if the tree view's nodes have children (nodes), try this instead:
List<string> values = new List<string>;
//Called by a button click or another control
private void getTreeValues(Object sender, EventArgs e)
{
foreach (string node in treeView.Nodes)
{
TreeNode child = (TreeNode)child;
values.Add(node)
getNodeValues(child);
}
foreach (string value in values)
{
Console.WriteLine(value + "\n");
}
}
//Recursive method which finds all children of parent node.
private void getNodeValues(TreeNode parent)
{
foreach (string child in parent.Nodes)
{
TreeNode node = (TreeNode)child;
values.Add(child);
if (nodes.Nodes.Count != 0) getNodeValues(child);
}
}