I have a diagram that I would like to update based on what the user clicks. Basically I want an organizational chart with two levels... the root level and its children. When a user clicks on a child of the root level then the child become the root and any children that it may have will appear below it.
When the user comes to the page I build the first two levels statically and the diagram loads and looks just fine:
But then when they click on a child node I load the new information from the database and it looks all messed up:
I can either use PopulateGraphSource or add the nodes and links in the loop, either way it turns out the same.
What am I doing wrong? I add the nodes and the links and then I call Layout - just like I do statically, but the links aren't connected to the nodes and the nodes are laid out all funky.
Attached is an example of the before and after I click on a child node.
When the user comes to the page I build the first two levels statically and the diagram loads and looks just fine:
Public Overrides Sub OnNavigatedTo(url As String, parameters As Dictionary(Of String, String))
Dim node1 As New Node With {.Name = "MAGTF", .Visibility = Visibility.Visible}
Me.RootNode = node1
Dim node2 As New Node With {.Name = "CE", .Rank = Rank.BrigadierGeneral, .AdvocateCode = AdvocateCode.CE}
Dim node3 As New Node With {.Name = "GGE", .Rank = Rank.BrigadierGeneral, .AdvocateCode = AdvocateCode.GCE}
Dim node4 As New Node With {.Name = "ACE", .Rank = Rank.BrigadierGeneral, .AdvocateCode = AdvocateCode.ACE}
Dim node5 As New Node With {.Name = "LCE", .Rank = Rank.BrigadierGeneral, .AdvocateCode = AdvocateCode.LCE}
node1.Children.Add(node2)
node1.Children.Add(node3)
node1.Children.Add(node4)
node1.Children.Add(node5)
Me.GraphSource.PopulateGraphSource(node1)
End Sub
But then when they click on a child node I load the new information from the database and it looks all messed up:
Private Sub RefillNodes(nodes As IEnumerable(Of Unit))
Me.GraphSource.Clear()
Me.RootNode.Children.Clear()
Me.GraphSource.AddNode(RootNode)
For Each Node As Unit In nodes
'Either this
Me.RootNode.Children.Add(New Node With {.Name = Node.Name, .Rank = Rank.Captain})
'Or this
'Me.GraphSource.AddNode(New Node With {.Name = Node.Name, .Rank = Rank.Captain})
'Me.GraphSource.AddLink(New Link(RootNode, New Node With {.Name = Node.Name, .Rank = Rank.Captain}))
Next
Me.GraphSource.PopulateGraphSource(RootNode)
End Sub
I can either use PopulateGraphSource or add the nodes and links in the loop, either way it turns out the same.
What am I doing wrong? I add the nodes and the links and then I call Layout - just like I do statically, but the links aren't connected to the nodes and the nodes are laid out all funky.
Attached is an example of the before and after I click on a child node.
17 Answers, 1 is accepted
0
Barry
Top achievements
Rank 1
answered on 15 May 2013, 02:11 PM
I figured out what I was doing wrong, I was trying to add a new node and then add a new link with a new node instead of the node that I just added.
This code works:
But oddly when I add multiple links the first link always ends up above the root... it only happens when I have more than one child.
This code works:
Dim newNode As Node
For Each Node As Unit In nodes
newNode = New Node With {.Name = Node.Name, .Rank = Rank.Major}
Me.GraphSource.AddNode(newNode)
Me.GraphSource.AddLink(New Link(Me.RootNode, newNode))
Next
But oddly when I add multiple links the first link always ends up above the root... it only happens when I have more than one child.
0
Barry
Top achievements
Rank 1
answered on 15 May 2013, 02:20 PM
I figured this one out too... I thought I saw a post about this and I was right.
All I had to do was reset the layout root.
All I had to do was reset the layout root.
0
Saher
Top achievements
Rank 1
answered on 16 Jul 2013, 09:53 PM
Hello,
I am facing a similar issue where my graph is tree layout and looks fine initially. However, if I choose to change GraphSource upon user input/ clicks using PopulateGraphSource like in the OrgChart example, I get all the nodes stacked on top of each other with no links and all in corner.
I tried resetting graphSource by creating a new one
I also tried to use the Clear method for GraphSource. Neither did solve the problem, I keep having the same issue.
I am facing a similar issue where my graph is tree layout and looks fine initially. However, if I choose to change GraphSource upon user input/ clicks using PopulateGraphSource like in the OrgChart example, I get all the nodes stacked on top of each other with no links and all in corner.
I tried resetting graphSource by creating a new one
this.graphSource = new GraphSource();
I also tried to use the Clear method for GraphSource. Neither did solve the problem, I keep having the same issue.
0
Barry
Top achievements
Rank 1
answered on 16 Jul 2013, 10:16 PM
You need to reset the root node(s) when you update the GraphSource...
0
Saher
Top achievements
Rank 1
answered on 16 Jul 2013, 10:28 PM
what does that mean?
How do I reset the Node object?
I am using
to fill up my GraphSource object.
All I do is create a new one and then call
method.
thanks
How do I reset the Node object?
I am using
ObservableCollection<
Node
> hierarchicalDataSource;
All I do is create a new one and then call
PopulateGraphSource();
thanks
0
Barry
Top achievements
Rank 1
answered on 16 Jul 2013, 10:38 PM
The
I don't know what is wrong with that method, but I could never get it to re-populate using that and not mess it up.
PopulateGraphSource()
is crap, you're better off adding nodes and links manually and then resetting the root node(s). I don't know what is wrong with that method, but I could never get it to re-populate using that and not mess it up.
0
Saher
Top achievements
Rank 1
answered on 16 Jul 2013, 11:09 PM
but this doesn't make sense:
PopulateGraphSource basically adds nodes and links recursively:
Thanks for your responses, I appreciate it.
PopulateGraphSource basically adds nodes and links recursively:
public void PopulateGraphSource(Node node)
{
this.AddNode(node);
foreach (Node subNode in node.Children){
Link link = new Link(node, subNode);
this.AddLink(link);
this.PopulateGraphSource(subNode);
}
}
Thanks for your responses, I appreciate it.
0
Barry
Top achievements
Rank 1
answered on 17 Jul 2013, 12:29 PM
Here's how I do it.
You have to make two properties:
Lets say that your RadDiagram is called OrgChart...
When you update your GraphSource, you need to reset the layout like this:
So you need to do this stuff after you re-populate your GraphSource. You can either do that using PopulateGraphSource (which may not work) or do it manually. Like I said, I do it manually.
My C# code may not be correct... I primarily use VB.
You have to make two properties:
private Telerik.Windows.Diagrams.Core.TreeLayoutSettings currentLayoutSettingsValue =
new Telerik.Windows.Diagrams.Core.TreeLayoutSettings();
public Telerik.Windows.Diagrams.Core.TreeLayoutSettings CurrentLayoutSettings {
get { return currentLayoutSettingsValue; }
set {
currentLayoutSettingsValue = value;
}
}
private TreeLayout TreeLayout;
Lets say that your RadDiagram is called OrgChart...
When you update your GraphSource, you need to reset the layout like this:
CurrentLayoutSettings.Roots.Clear();
foreach (var node in hierarchicalDataSource) {
if (node.Children.Count > 0) {
CurrentLayoutSettings.Roots.Add(OrgChart.Shapes.Where(s => s.Content.Equals(node)).FirstOrDefault);
}
}
TreeLayout.Layout(OrgChart, CurrentLayoutSettings);
So you need to do this stuff after you re-populate your GraphSource. You can either do that using PopulateGraphSource (which may not work) or do it manually. Like I said, I do it manually.
My C# code may not be correct... I primarily use VB.
0
Saher
Top achievements
Rank 1
answered on 17 Jul 2013, 05:45 PM
Hi Barry,
I appreciate your reply. Thank You.
Unfortunately, this did not work. I get the nodes but everything looks messed up as if there is no root node, the links look weird.
again, I am not sure I understand difference between manual and PopulateGraphSource, PopulateGraphSource I override as follows:
Isn't that what you will manually do?
I tried calling these before graph re-population:
but with same result. What other options I can try?
why creating a new GraphSource object doesn't solve it? This is so confusing.
I appreciate your reply. Thank You.
Unfortunately, this did not work. I get the nodes but everything looks messed up as if there is no root node, the links look weird.
again, I am not sure I understand difference between manual and PopulateGraphSource, PopulateGraphSource I override as follows:
public void PopulateGraphSource(Node node)
{
this.AddNode(node);
foreach (Node subNode in node.Children)
{
Link link = new Link(node, subNode);
this.AddLink(link);
this.PopulateGraphSource(subNode);
}
}
Isn't that what you will manually do?
I tried calling these before graph re-population:
this.GraphSource.Clear();
this.GraphSource.InternalItems.Clear();
this.GraphSource.InternalLinks.Clear();
why creating a new GraphSource object doesn't solve it? This is so confusing.
0
Barry
Top achievements
Rank 1
answered on 17 Jul 2013, 05:53 PM
Can you post your code of what you're doing when you re-populate the GraphSource?
There really is no difference between PopulateGraphSource and doing it manually. I just had issues with it when I first tried it, like you are, and gave up on using it.
There really is no difference between PopulateGraphSource and doing it manually. I just had issues with it when I first tried it, like you are, and gave up on using it.
0
Saher
Top achievements
Rank 1
answered on 17 Jul 2013, 06:21 PM
the click event does the following:
PopulateGraphSources() defined:
Then I apply the code you suggested:
The OnLoaded function defined:
Thanks
this.RelTreeDataSource = getData(selection); //this returns an ObservableCollection<
Node
> object
this.PopulateGraphSources();
private void PopulateGraphSources()
{
foreach (var item in this.RelTreeDataSource)
{
this.GraphSource.PopulateGraphSource(item);
}
}
public void PopulateGraphSource(Node node)
{
this.AddNode(node);
foreach (Node subNode in node.Children)
{
Link link = new Link(node, subNode);
this.AddLink(link);
this.PopulateGraphSource(subNode);
}
}
Then I apply the code you suggested:
ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Clear();
foreach (var node in RelTreeDataSource)
{
if (node.Children.Count > 0)
{
ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Add(diagram.Shapes.Where(s => s.Content.Equals(node)).FirstOrDefault());
}
}
OnLoaded(sender, e);
this.diagram.RoutingService.Router = this.Router;
Dispatcher.BeginInvoke(() => this.treeLayout.Layout(this.diagram, this.ChildTreeLayoutViewModel.CurrentLayoutSettings));
The OnLoaded function defined:
foreach (var item in this.RelTreeDataSource)
{
RadDiagramShape shape = this.diagram.ContainerGenerator.ContainerFromItem(item) as RadDiagramShape;
this.ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Add(shape);
}
this.diagram.Layout(LayoutType.Tree);
//suspend auto update
this.diagram.Connections.ForEach(x => RadDiagramConnection.SetIsAutoUpdateSuppressed((RadDiagramConnection)x, true));
this.CurrentTreeLayoutType = TreeLayoutType.TreeDown;
this.treeLayout.Layout(this.diagram, ChildTreeLayoutViewModel.CurrentLayoutSettings);
//undo suspend
this.diagram.Connections.ForEach(x => RadDiagramConnection.SetIsAutoUpdateSuppressed((RadDiagramConnection)x, false));
this.diagram.Connections.ForEach(x => x.Update());
if(shouldAutoFit)
this.diagram.AutoFit(new Thickness(10), false);
Dispatcher.BeginInvoke(() => this.treeLayout.Layout(this.diagram, ChildTreeLayoutViewModel.CurrentLayoutSettings));
Thanks
0
Saher
Top achievements
Rank 1
answered on 17 Jul 2013, 06:27 PM
the click event does the following:
PopulateGraphSources() defined:
Then I apply the code you suggested:
The OnLoaded function defined:
Thanks
this.RelTreeDataSource = getData(selection); //this returns an ObservableCollection<
Node
> object
this.PopulateGraphSources();
private void PopulateGraphSources()
{
foreach (var item in this.RelTreeDataSource)
{
this.GraphSource.PopulateGraphSource(item);
}
}
public void PopulateGraphSource(Node node)
{
this.AddNode(node);
foreach (Node subNode in node.Children)
{
Link link = new Link(node, subNode);
this.AddLink(link);
this.PopulateGraphSource(subNode);
}
}
Then I apply the code you suggested:
ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Clear();
foreach (var node in RelTreeDataSource)
{
if (node.Children.Count > 0)
{
ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Add(diagram.Shapes.Where(s => s.Content.Equals(node)).FirstOrDefault());
}
}
OnLoaded(sender, e);
this.diagram.RoutingService.Router = this.Router;
Dispatcher.BeginInvoke(() => this.treeLayout.Layout(this.diagram, this.ChildTreeLayoutViewModel.CurrentLayoutSettings));
The OnLoaded function defined:
foreach (var item in this.RelTreeDataSource)
{
RadDiagramShape shape = this.diagram.ContainerGenerator.ContainerFromItem(item) as RadDiagramShape;
this.ChildTreeLayoutViewModel.CurrentLayoutSettings.Roots.Add(shape);
}
this.diagram.Layout(LayoutType.Tree);
//suspend auto update
this.diagram.Connections.ForEach(x => RadDiagramConnection.SetIsAutoUpdateSuppressed((RadDiagramConnection)x, true));
this.CurrentTreeLayoutType = TreeLayoutType.TreeDown;
this.treeLayout.Layout(this.diagram, ChildTreeLayoutViewModel.CurrentLayoutSettings);
//undo suspend
this.diagram.Connections.ForEach(x => RadDiagramConnection.SetIsAutoUpdateSuppressed((RadDiagramConnection)x, false));
this.diagram.Connections.ForEach(x => x.Update());
if(shouldAutoFit)
this.diagram.AutoFit(new Thickness(10), false);
Dispatcher.BeginInvoke(() => this.treeLayout.Layout(this.diagram, ChildTreeLayoutViewModel.CurrentLayoutSettings));
Thanks
0
Hi Saher,
Hristo
Telerik
As I have noted in the other forum post you created here, the best way to proceed would be to investigate your project in order to find the root cause for your issues. This would be the fastest way to assist you in finding a solution.
Also, as soon as we solve the issue in the other thread, I will make sure to update this forum to reflect our findings.
Hristo
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Alvise
Top achievements
Rank 1
answered on 13 Mar 2017, 02:09 PM
Hi,
Can you provide the solution to Saher's issue?
Thanks!
0
Hello guys,
The behavior with the wrong layout and the connections that are not properly linked, comes from the fact that the order of adding links and connections in the GraphSource is not set up as it should be. Basically, all nodes should be added in the graph source before the links that connect them. Otherwise, the connection could be missed when the visual elements are created (RadDiagramShape and RadDiagramConnection).
So, in this specific case (the OrgChart example), the issue comes from the PopulateGraphSource() method. In order to resolve this you can switch the lines of code in the "foreach" loop. Here is an example:
I hope this helps.
Regards,
Martin
Telerik by Progress
The behavior with the wrong layout and the connections that are not properly linked, comes from the fact that the order of adding links and connections in the GraphSource is not set up as it should be. Basically, all nodes should be added in the graph source before the links that connect them. Otherwise, the connection could be missed when the visual elements are created (RadDiagramShape and RadDiagramConnection).
So, in this specific case (the OrgChart example), the issue comes from the PopulateGraphSource() method. In order to resolve this you can switch the lines of code in the "foreach" loop. Here is an example:
public
void
PopulateGraphSource(Node node)
{
this
.AddNode(node);
foreach
(Node subNode
in
node.Children)
{
this
.PopulateGraphSource(subNode);
Link link =
new
Link(node, subNode);
this
.AddLink(link);
}
}
I hope this helps.
Regards,
Martin
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which
deliver the business app essential building blocks - a grid component,
data visualization (charts) and form elements.
0
Luc
Top achievements
Rank 1
answered on 08 Jun 2017, 12:11 PM
Tnx Martin!
Adapting PopulateGraphSource() by putting the recursive call before the link creation code solved a similar issue for me. I am now able to repopulate the diagram ... . Have been studying the component for several hours, not suspecting the demo code ;-(
Regards,
Luc Vervoort
0
Hi Luc,
I am glad to hear that the given solution helps.
Regards,
Martin Ivanov
Progress Telerik
I am glad to hear that the given solution helps.
Regards,
Martin Ivanov
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which
deliver the business app essential building blocks - a grid component,
data visualization (charts) and form elements.