Reputation: 2686
I am trying to make a treeView that have items in the following order.
+ Continent
+ Country
+ Province
+ Territory
And, I have a generic class to hold the treeView Items data.
public class TreeViewContinents
{
public List<TreeViewContinents> Children { get; set; }
public TreeViewContinents Parent { get; set; }
public string Name { get; set; }
public string Content { get; set; }
}
Data:
private readonly List<Dictionary<string, object>> continentsList = new List<Dictionary<string, object>>();
/*
continentsList[0] - "Continent", "Asia"
"Country", "Afghanistan"
"Province", "Kabul"
"Territory", "Bagrami"
"Language", "aaa"
"Culture", "bbb"
.
.
.
.
continentsList[n] - "Continent", "North America"
"Country", "Canada"
"Province", "Ontario"
"Territory", "Ottawa"
"Language", "aaa"
"Culture", "bbb
*/
String array based on which treeView Items needs to be generated.
var treeViewItemNames = new[] { "Continent", "Country", "Province", "Territory" };
Code:
List<object> Continents = this.continentsList.Where(
p_oDict => p_oDict.ContainsKey(treeViewItemNames[0]))
.Select( p_oDict => p_oDict[treeViewItemNames[0]])
.Distinct()
.ToList();
var topItems = new List<TreeViewContinents>();
foreach (object continent in Continents)
{
var level1Items = new TreeViewContinents { Name = treeViewItemNames[0], Content = continent.ToString() };
List<object> Countries = this.continentsList.Where(
p_oDict => p_oDict.ContainsKey(treeViewItemNames[0])
&& p_oDict.ContainsKey(treeViewItemNames[1])
&& p_oDict[treeViewItemNames[0]].Equals(continent)
.Select( p_oDict => p_oDict[treeViewItemNames[1]])
.Distinct()
.ToList();
Countries.Sort((p_oU1, p_oU2) => string.Compare(p_oU1.ToString(), p_oU2.ToString(), StringComparison.Ordinal));
foreach (object country in Countries)
{
var level2Items = new TreeViewContinents { Name = treeViewItemNames[1], Content = country.ToString(), Parent = level1Items };
level1Items.Children.Add(level2Items);
List<object> Provinces = this.continentsList.Where(
p_oDict => p_oDict.ContainsKey(treeViewItemNames[0])
&& p_oDict.ContainsKey(treeViewItemNames[1])
&& p_oDict.ContainsKey(treeViewItemNames[2])
&& p_oDict[treeViewItemNames[0]].Equals(continent)
&& p_oDict[treeViewItemNames[1]].Equals(country))
.Select( p_oDict => p_oDict[treeViewItemNames[2]]).Distinct()
.ToList();
Provinces.Sort((p_oU1, p_oU2) => string.Compare(p_oU1.ToString(), p_oU2.ToString(), StringComparison.Ordinal));
foreach (object province in Provinces)
{
var level3Items = new TreeViewContinents { Name = treeViewItemNames[2], Content = province.ToString(), Parent = level2Items };
level2Items.Children.Add(level3Items);
List<object> Territories = this.continentsList.Where(
p_oDict => p_oDict.ContainsKey(treeViewItemNames[0])
&& p_oDict.ContainsKey(treeViewItemNames[1])
&& p_oDict.ContainsKey(treeViewItemNames[2])
&& p_oDict.ContainsKey(treeViewItemNames[3])
&& p_oDict[treeViewItemNames[0]].Equals(continent)
&& p_oDict[treeViewItemNames[1]].Equals(country)
&& p_oDict[treeViewItemNames[2]].Equals(province)).Select(
p_oDict => p_oDict[treeViewItemNames[3]])
.Distinct()
.ToList();
Territories.Sort((p_oU1, p_oU2) => string.Compare(p_oU1.ToString(), p_oU2.ToString(), StringComparison.Ordinal));
foreach (object territory in Territories)
{
var level4Items = new TreeViewContinents { Name = treeViewItemNames[3], Content = territory.ToString(), Parent = level3Items };
level3Items.Children.Add(level4Items);
}
}
}
topItems.Add(level1Items);
}
In the above code, I have four foreach loops to build a treeview. Is it possible to write a single loop to generate the treeView based on the the variable treeViewItemNames
, so that in future If i change the variable like
var treeViewItemNames = new[] { "Continent", "Country", "Territory" };
it should generate treeView like this
+ Continent
+ Country
+ Territory
Ideas/ Suggestions please.
Upvotes: 0
Views: 185
Reputation: 6301
I suggest to iterage through continentsList elements.
var treeViewItemNames = new[] { "Continent", "Country", "Province", "Territory" };
var topItems = new List<TreeViewContinents>();
foreach (var continent in continentsList)
{
List<TreeViewContinents> currentLevel = topItems;
TreeViewContinents parentItem = null;
foreach (var sectionTitle in treeViewItemNames)
{
String value = Convert.ToString(continent[sectionTitle]);
TreeViewContinents currentItem = currentLevel.FirstOrDefault(tree => tree.Content == value);
if (currentItem == null)
{
currentItem = new TreeViewContinents { Name = sectionTitle, Content = value };
currentItem.Children = new List<TreeViewContinents>();
if (parentItem != null)
{
currentItem.Parent = parentItem;
}
currentLevel.Add(currentItem);
}
parentItem = currentItem;
currentLevel = currentItem.Children;
}
}
The problem with this code is that there is no sorting in items, but we can sort the resulting TreeViewContinents list. Here is recursive method for sorting:
public List<TreeViewContinents> SortTreeView(List<TreeViewContinents> treeViewList)
{
foreach (var item in treeViewList)
{
if (item.Children.Count > 0)
{
item.Children = SortTreeView(item.Children);
}
}
return treeViewList.OrderBy(it => it.Content).ToList();
}
You can use it after topItems list is full:
topItems = SortTreeView(topItems);
Upvotes: 1