Referring to http://es.infragistics.com/samples/wpf/diagram/binding-nodes-with-objects
Can you please suggest recommended way of aligning new nodes if a child node is created on fly. I have set TreeDiagramLayout's NodeFlowDirection to "Below" but when a new object is added in viewmodel at run time it goes to top left corner of diagram.
Ideally starting from parent, I would like nodes to be center aligned and newly created to be below parent node.
Hello Abs,
The diagram layout is applied only initially to the diagram. If the items are added/removed later (eg. view model collection), the layout is not automatically applied. In order to rearrange the nodes at a later stage, call the RefreshLayout method directly on the XamDiagram.
eg.
mainWindow.Diagram.RefreshLayout();
For more details please visit:http://es.infragistics.com/help/wpf/xamdiagram-configuring-the-layout
If you require a custom position you can use the diagram's items collection changed event to do so:
private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { FamilyTreeViewModel vm = this.Diagram.DataContext as FamilyTreeViewModel;
if (e.NewStartingIndex >= vm.FamilyTree.Count) { if (e.NewItems[0] is DiagramNode) {
DiagramNode newlyAdded = e.NewItems[0] as DiagramNode; newlyAdded.Position = new Point(50, 50); } } }
Let me know if you have any questions regarding this matter.
Thank you for these ideas. This link is broken for me!
http://help.infragistics.com/Help/Doc/WPF/2016.2/CLR4.0/html/xamDiagram_Configuring_the_Layout.html
I've updated my post above with the correct link.
http://es.infragistics.com/help/wpf/xamdiagram-configuring-the-layout
Let me know if you have any questions.
Hi Michael,
I have looked the link on how to configure custom layout which look great, however I can not locate ItemCollectionChanged event in diagram or diagram's items collection to call RefreshLayout function.
http://help.infragistics.com/doc/WPF/2016.1/CLR4.0/?page=InfragisticsWPF4.Controls.Charts.XamDiagram.v16.1~Infragistics.Controls.Charts.XamDiagram_members.html
I have attached an example with this post can you please suggest the right event? I would like to retain TreeDiagramLayout implemented by infragistics and no custom layout is required.
Also, I would like user to be able to move diagram nodes horizontally and restrict any vertical movement in diagram.
The XamDiagram contains an Items collection. This member exposes a CollectionChanged event:http://es.infragistics.com/help/wpf/infragisticswpf4.controls.charts.xamdiagram.v16.2~infragistics.controls.charts.diagramitemscollection_members Eg.
Diagram.Items.CollectionChanged += Items_CollectionChanged;
You can handle the diagram's NodeMoving event, create a new Point for the node based on the old Y position and cancel it whenever the Node's Y attempts to change. I've tested this and the nodes move only in a horizontal direction.
private void Diagram_NodeMoving(object sender, DiagramNodeMovingEventArgs e) { if (e.OldPosition.Y != e.NewPosition.Y) { Point nodePoint = new Point(e.NewPosition.X, e.OldPosition.Y); e.Node.Position = nodePoint; e.Cancel = true; } }
Thanks Michael for the code sample to restrict vertical movement.
I am getting KeyNotFoundException with "The given key was not present in the dictionary" message when RefreshLayout is called on diagram's items CollectionChanged event.
This is a timing issue, since this event is firing well before nodes are displayed on-screen.
You can easily work around this by placing an if-check to determine if you have any shapes on-screen based on what is found in the datasource, otherwise you won't need to refresh the layout.
if (e.NewStartingIndex >= vm.FamilyTree.Count) { this.Diagram.RefreshLayout(); } }
Ok, thank you for the suggestion.
Thank you for following up. This again is related to the time it takes to load the nodes and the layout. Please wrap the RefreshLayout method inside an asyncronyons Dispatcher.BeginInvoke method:
private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { MainWindowViewModel vm = this.EmployesDiagram.DataContext as MainWindowViewModel;
if (e.NewStartingIndex >= vm.Employees.Count) { Dispatcher.Invoke(async () => { this.EmployesDiagram.RefreshLayout(); }); } }
You can use the same code you attached and select any leaf node and then add a new node, it raises an exception.
Is this still an issue? Please provide some code snippet in the CollectionChanged event and I will take a look.
Thanks for coming back to me, I had the same code and exception is raised when a node is added to the leaf node.