which is the best way to build the tree view control using string collection
-
15-03-2021 - |
Question
I am trying to prepare the tree view control from folowing strings.
"US|New York|D.M.Street"
"US|New York|ShoppingMall"
"INDIA|Dehli|G.M. Road"
"INDIA|Mumbai|Harbour Street"
"US|Washington|WhiteHouse"
"INDIA|Dehli|Rajpath"
"INDIA|Mumbai|CST"
I want to populate the tree view from this collection in C#. in following manner
Country
|
US => NewYork ==========>D.M.Street
| | ==========>ShoppingMall
|
| Washinton==========>WhiteHouse
|
INDIA=>Dehli ==========>G.M. Road
| ==========>Rajpath
|
Mumbai ==========>CST
==========>Harbour Street
how i can prepare this ? usning collection or else way?
Solution
Here's how I would approach this:
Create a class and a collection to hold a nested hierarchy of elements (this can be expanded later if more detail is needed).
public class Element
{
public Element(string Name)
{
this.Name = Name;
}
public string Name { get; set; }
public ElementCollection Children = new ElementCollection();
// This method is used to add the specified child name if it does not currently
// exist, or return the existing one if it does
public Element AddOrFetchChild(string sName)
{
Element oChild;
if (this.Children.ContainsKey(sName))
{
oChild = this.Children[sName];
}
else
{
oChild = new Element(sName);
this.Children.Add(sName, oChild);
}
return oChild;
}
}
public class ElementCollection : System.Collections.Generic.Dictionary<string, Element>
{
}
Then parse your data into the collection (note that this will support any level of nesting in your record structure without a need to modify the code):
string[] asLines;
// ToDo: Add code here to populate the collection of lines to process
// Create a base element that makes popuplation of the elements easier
Element BaseElement = new Element("");
// Cycle through each of the lines
foreach (string sLine in asLines())
{
// Get the components out of the line
string[] asElements = sLine.Split("|");
// Starting with the base element
Element oParentElement = BaseElement;
// Cycle through each of the elements that were found, adding the current value to the parent's
// collection of children, then using the new or found item as the parent for the next item in the list
for (int nI = 0; nI < asElements.Length; nI++)
{
oParentElement = oParentElement.AddOrFetchChild(asElements[nI]);
}
}
// Finally, add the nodes to the tree recursively
AddNodesToTree(BaseElement.Children, this.treeView1.Nodes);
and this is the recursive method used to add the items to the tree
/// <summary>
/// A recursive method to add all of the records to the specified collection of nodes
/// </summary>
/// <param name="cRecords"></param>
/// <param name="cNodes"></param>
private void AddNodesToTree(ElementCollection cRecords, TreeNodeCollection cNodes)
{
foreach (Element oRecord in cRecords.Values)
{
TreeNode oNode = new TreeNode();
oNode.Text = oRecord.Name;
oNode.Tag = oRecord;
cNodes.Add(oNode);
// Now add the node's children if any
if (oRecord.Children.Count != 0)
{
AddNodesToTree(oRecord.Children, oNode.Nodes);
}
}
}
OTHER TIPS
Given a GetData()
function that returns IEnumerable<string>
with all of the string data, and assuming you want a jumble of LINQ:
var nodes = GetData().Select(data => data.Split('|')).GroupBy(x => x[0]).Select(
country => new TreeNode(country.Key, country.GroupBy(x => x[1]).Select(
city => new TreeNode(city.Key, city.Select(
place => new TreeNode(place[2]))
.ToArray()))
.ToArray()))
.ToArray();
treeView1.Nodes.AddRange(nodes);
Note that this does not account for the inconsistent spellings of "New York" and "Mumbai" in your sample data, which I have corrected in the sample.