I'm using this code from the another web:
How can I model this class in a database?
I have in each objective record a field named "Rank". It tells me what position is. For instance:
Objective "Geometry": Rank1
|_Objective "Squares": Rank1
|_Objective "Circles": Rank2
|_Objective "Triangle": Rank3
|_Objective "Types": Rank1
Objectve "Algebra": Rank2
Objective "Trigonometry": Rank3
That rank tells me the order of the nodes. But I want to get all the rank: For the third position will be:
Objective "Geometry": Rank1
|_Objective "Squares": Rank1 -> 1.1
|_Objective "Circles": Rank2
|_Objective "Triangle": Rank3
|_Objective "Types": Rank1 -> 1.3.1
Objectve "Algebra": Rank2
Objective "Trigonometry": Rank3 -> 3
I'm using LINQ to SQL. How can I do that?
<TreeView Name="treeView1">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type data:Objective}" ItemsSource="{Binding Path=Objectives}" >
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I'm not sure if I understand what you want, but it's pretty straightforward to walk the tree recursively and assign ranks to the objects. Here's some quick code I whipped up:
public void Test()
{
Objective math = Init();
RankObjective("", math);
System.Console.ReadLine();
}
private void RankObjective(string rank, Objective objective)
{
int count = 1;
if (!String.IsNullOrEmpty(rank))
Console.WriteLine(objective.Name + ": " + rank);
foreach (Objective child in objective.Objectives)
{
string newRank = String.IsNullOrEmpty(rank) ? count.ToString() : rank + "." + count.ToString();
RankObjective(newRank, child);
count++;
}
}
private Objective Init()
{
Objective math = new Objective("Math");
Objective geometry = new Objective("Geometry");
geometry.Objectives.Add(new Objective("Squares"));
geometry.Objectives.Add(new Objective("Circles"));
Objective triangle = new Objective("Triangle");
triangle.Objectives.Add(new Objective("Types"));
geometry.Objectives.Add(triangle);
math.Objectives.Add(geometry);
math.Objectives.Add(new Objective("Algebra"));
math.Objectives.Add(new Objective("Trigonometry"));
return math;
}
using this class:
public class Objective
{
public Objective(string name)
{
Name = name;
Objectives = new List<Objective>();
}
public string Name { get; set; }
public List<Objective> Objectives { get; set; }
}
output:
Geometry: 1
Squares: 1.1
Circles: 1.2
Triangle: 1.3
Types: 1.3.1
Algebra: 2
Trigonometry: 3
Start with something like:
void main()
{
foreach(Node root in nodeCollection)
{
this.Recursion(root, 1);
}
}
void Recursion(Node n, int depth)
{
node.Depth = depth;
foreach(Node child in n.Children)
{
this.Recursion(child, depth++);
}
}
This will give you a Depth for each node (of course you have to add the field Node to your class).
By far the easiest way to implement this is in the model or view model. For instance, in your Node
class, you could implement the following properties:
public Collection<Node> Siblings { /* see below */ }
public Collection<Node> Children { get; set; }
public Node Parent { get; set; }
public int Position
{
get
{
return (Parent == null)
? 0 // I don't like magic numbers, but I don't want to make this an int? either
: Siblings.IndexOf(this) + 1;
}
}
public string Rank
{
get
{
return (Parent == null)
? Position.ToString()
: Parent.Rank + "." + Position.ToString();
}
}
Usually, the simplest way to implement a Siblings
property is
public Collection<Node> Siblings
{
get
{
return (Parent == null)
? null
: Parent.Children;
}
}
That doesn't work in the case where there is a collection of top-level nodes that's not part of the node hierarchy, like this. You can dummy this up by creating a root Node
object that doesn't appear in your UI - in this case, you'd bind the TreeView
to the root node's Children
property, and implement Rank
like this:
public string Rank
{
get
{
if (Parent == null)
{
return null;
}
if (Parent.Parent == null)
{
return Position.ToString();
}
return Parent.Rank + "." + Position.ToString();
}
}