We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Different kinds of Nodes

Hi,

I'm currently developing a UWP application that uses the Diagram Component.

In my model i have these different clasess :

GenericComponent (ParentClass) (CommonProperty1,CommonProperty2, CommonNode)

     - ComponentA (PropertyA,PropertyB,PropertyC) [ShapeStyle1]
     - ComponentB (PropertyD,PropertyF,PropertyD) [ShapeStyle2]
     - ComponentC (....PropertyM) [ShapeStyle3]

Each of those classes should be represented for a Rectangle Shape in the diagram and a different content template for each one.

After that i want to create an ObservableCollection<GenericComponent> where i can have different objects from this different classess.

Each time i execute componentsCollection.Add(new ComponentA()) => This should create a Object inside the collection and also add it's node to the diagram (the node is the visual representation of the object).

Right now i have two ObservableCollections, everytime i add a component it will loop the collection and add each node to the second collection. This is not the right way to do it and also is not working i get An item with the same key has already been added

What could be the best approach to achieve this?
Thanks




7 Replies

KR Keerthivasan Ramamoorthy Syncfusion Team February 20, 2018 12:26 PM UTC

Hi Fede, 
Please find the responses to your queries as below. 
 
S.no 
Query 
Response 
 
In my model i have these different clasess :

GenericComponent (ParentClass) (CommonProperty1,CommonProperty2, CommonNode)

     - ComponentA (PropertyA,PropertyB,PropertyC) [ShapeStyle1]
     - ComponentB (PropertyD,PropertyF,PropertyD) [ShapeStyle2]
     - ComponentC (....PropertyM) [ShapeStyle3]

Each of those classes should be represented for a Rectangle Shape in the diagram and a different content template for each one.

After that i want to create an ObservableCollection<GenericComponent> where i can have different objects from this different classess.
 
Each time i execute componentsCollection.Add(new ComponentA()) => This should create a Object inside the collection and also add it's node to the diagram (the node is the visual representation of the object). 
We have prepared a simple sample for your requirement.  Please find the sample and screenshot as below. 
 
 
Screenshot: 
 
 
Sample details: 
We have created 3 classes, GenericComponent derives NodeViewModel. ComponentA and ComponentB derives GenericComponent. We have also added properties in it. We have 2 different data templates for component A and B. By default content is null, we have assigned the content property as Component to itself(self-reference), this will enable binding between template and properties of the component. 
 
Following some of the ways you can organize your data structure. 
  1. You can derive NodeViewModel for your business object (GenericComponent: NodeViewModel)
  2. You can implement INode interface for your business object (GenericComponent: INode)
  3. You can avoid deriving or implementing diagram objects, and assign your business object as Content of NodeViewModel (node.Content = new ComponentA())
3 
Right now i have two ObservableCollections, everytime i add a component it will loop the collection and add each node to the second collection. 
It is possible to set only one collection to SfDiagram.Nodes. We are not sure how are you using 2 different collection and use it for diagram. Please provide some code snippets or a sample to demonstrate your usage. 
4 
This is not the right way to do it and also is not working i get An item with the same key has already been added 
The reported issue occurred only if we add the same instance to Nodes or Connectors collection of the Diagram. You should not add duplicate objects for SfDiagram.Node or SfDiagram.Connector. Can you please ensure your side whether the collection having different instance? 
 
 
Regards, 
Keerthivasan R. 



DY Dylan February 20, 2018 08:23 PM UTC

I've been able to achieve my previous requests,

I would like to know a few more things...

1) How do you disable the Menu (Rotation,Delete, Connection) when you click the node? I'm referring to => https://www.dropbox.com/s/eu9kg3ymkn939bg/Menu.PNG?dl=0

2) I've been able to create dynamic ports some nodes, for example ComponentA have only an out port, others have an out and in port and others have 4 ports (2 in , 2 out) in the attached file you can see how i did it, do you think is there a better way?

3) When you zoom in the Ports get bigger and when you zoom out the ports get smaller, this should not work like this, is there any way to fix it?

4) As you can see in the attached project i have a button inside the ContentTemplate what is the best way to be able to execute a click? Using findvisualchildren? , ICommand?

5) How do i get the selected item in the diagram? I'm using SelectedItems but i would like to only get one...

6) I would like to Start dragging and creating a connector from the port to another port, however right now i cant create connections from the ports or from the create connector button in the node menu, how i do it?

PROJECT
https://www.dropbox.com/s/nibo7j7ykokx89h/135998_Sample-633443148.rar?dl=0

Thank you so much




KR Keerthivasan Ramamoorthy Syncfusion Team February 21, 2018 12:35 PM UTC

Hi Dylan, 
 
Please find the responses to your queries as below. 
 
 
S.no 
Query 
Response 
1 
  How do you disable the Menu (Rotation,Delete, Connection) 
when you click the node? I'm referring to =>  
 
 
We have an option to enable or disable the Quickcommand for the Node. Please find the code example to disable the QuickCommand for Node and also refer the kb link. 
 
Code Example: 
//Enable or disable the quickcommand 
(diagram.SelectedItems as SelectorViewModel).SelectorConstraints &= ~SelectorConstraints.QuickCommands; 
 
 
 
Screenshot: 
 
 
2 
I've been able to create dynamic ports some nodes, for example ComponentA have only an out port, others have an out and in port and others have 4 ports (2 in , 2 out) in the attached file you can see how i did it, do you think is there a better way? 
We have modified the sample to meet your requirement. Please find the sample from the attachment. 
Code example: 
if (this is Product) 
{ 
GenerateOutPort(this, .5, 1, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
GenerateOutPort(this, 0, .5, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
} 
else if (this is Pallet) 
{ 
GenerateInPort(this, .5, 1, PortConstraints.InConnect & ~PortConstraints.InheritPortVisibility); 
GenerateOutPort(this, 0, .5, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
} 
else if (this is Robot) 
{ 
GenerateOutPort(this, .5, 1, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
GenerateOutPort(this, 0, .5, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
GenerateInPort(this, 0, .5, PortConstraints.InConnect & ~PortConstraints.InheritPortVisibility); 
GenerateInPort(this, 1, .5, PortConstraints.InConnect & ~PortConstraints.InheritPortVisibility); 
} 
else if (this is PalletStation) 
{ 
GenerateOutPort(this, .5, 1, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
GenerateOutPort(this, 0, .5, PortConstraints.OutConnect & ~PortConstraints.InheritPortVisibility); 
GenerateInPort(this, 0, .5, PortConstraints.InConnect & ~PortConstraints.InheritPortVisibility); 
GenerateInPort(this, 1, .5, PortConstraints.InConnect & ~PortConstraints.InheritPortVisibility); 
} 
 
//Outport 
public CustomPortVM GenerateOutPort(CustomNodeVM node, double offx, double offy, PortConstraints constraints) 
{ 
CustomPortVM OutPort = new CustomPortVM() 
{ 
UnitWidth = 20, 
UnitHeight = 20, 
NodeOffsetX = offx, 
ConnectionDirection = ConnectionDirection.Right, 
NodeOffsetY = offy, 
PortVisibility = PortVisibility.ValidConnection, 
Constraints = constraints, 
Shape = new EllipseGeometry() { RadiusX = 10, RadiusY = 10 }, 
ShapeStyle = App.Current.Resources["portstyle"] as Style, 
}; 
if (node.Ports == null) 
{ 
node.Ports = new ObservableCollection<IPort>(); 
 
} 
(node.Ports as ObservableCollection<IPort>).Add(OutPort); 
return OutPort; 
} 
//Inport 
public CustomPortVM GenerateInPort(CustomNodeVM node, double offx, double offy, PortConstraints constraints) 
{ 
CustomPortVM OutPort = new CustomPortVM() 
{ 
UnitWidth = 20, 
UnitHeight = 20, 
NodeOffsetX = offx, 
NodeOffsetY = offy, 
PortVisibility = PortVisibility.ValidConnection, 
Constraints = constraints, 
Shape = new EllipseGeometry() { RadiusX = 10, RadiusY = 10 }, 
ShapeStyle = App.Current.Resources["portstyle"] as Style, 
}; 
if (node.Ports == null) 
{ 
node.Ports = new ObservableCollection<IPort>(); 
 
} 
(node.Ports as ObservableCollection<IPort>).Add(OutPort); 


DY Dylan March 20, 2018 06:27 PM UTC

Hello again and thanks for all of your help, i'm here with more questions and a few errors:

Errors
----------------------------------------

- Diagram is incredibly slow with 5-10 nodes, dragging and zooming is terrible
- I'm having a lot of unknown crashes when diagram loses the focus and then i click an element

Crash 1 (Diagram element loses its focus, splitpanel opens and then it crash)
Exception thrown: read access violation.
this was 0xD2E052D9.

Crash 2 (ramdom while using nodes)
pReference+20-> was nullptr UWP

Crash 3 (Diagram element loses focus, splitpanel opens, click on propertygrid, back to diagram and crash)
Exception thrown: read access violation.
this was 0x2F0735AF


- Undo and Redo are not working using (graphinfo.Commands.Undo.Execute(null)) crashes the app (NullReferenceException)

Questions
----------------------------------------------------------------------------------------------

- Let's say i want ComponentA to be compatible with ComponentB, so if i have a dictionary where i specify a valid connection given 2 types, and if ComponentA-Port (Source) is Out and ComponentB-Port is In (Target) complete the connection. If dictionary returns false, connection would be incompatible, for example ComponentA and ComponetC, how can i accomplish this?

- How can you disable the blue square animation when you try to create a connection in a port?

- How to remove/disable all of the node adorners, including rotation and gray points and position values as seen in this photo:

https://www.dropbox.com/s/tcxytgzlf5mzqjx/adorners.png?dl=0

- Why are keyboard commands disabled? I cannot use del to remove a node or cntrl+c to copy nodes

Here you can download the project

https://www.dropbox.com/s/7wajnapyuhgx7gv/PRO.rar?dl=0




KR Karkuvel Rajan Shanmugavel Syncfusion Team March 21, 2018 02:00 PM UTC

Hi Dylan,  
  
We have analysed all the Queries in simple sample. Please provide necessary Actipro dll to validate your Project. Please find the responses to your queries as below.  
 
S.No 
Query 
Response 
1, 3 
Diagram is incredibly slow with 5-10 nodes, dragging and zooming is terrible 
 
random while using nodes
pReference+20-> was nullptr UWP 
We are not able to run application due to missing ActiPro dll. Could you please provide the necessary dll to reproduce the issue in your application? 
2,4. 
1.Diagram element loses its focus, splitpanel opens and then it crash
Exception thrown: read access violation.
 
 
2.Diagram element loses focus, splitpanel opens, click on propertygrid, back to diagram and crash
Exception thrown: read access violation. 
We were able to reproduce the reported issues and  we will fix them in the next Service Pack 1 Release in the last week of March. 
5. 
Undo and Redo are not working using (graphinfo.Commands.Undo.Execute(null)) crashes the app (NullReferenceException) 
By default, the Undo and Redo options are disabled. Trying Undo and Redo without enabling, will lead to null reference excpetion. We have to enable the Undoable in Diagram Constraints. Please follow the code example. 
 
Code Example: 
 
diagram.Constraints |= GraphConstraints.Undoable; 
 
6. 
Validate Connection  
If method returns false , connection should be incompatible. 
You can validate a connection created at runtimg using CanConnect virtual method of NodePort. This will be called when you try to connect using DrawingTool. Please refer code example. 
 
Code Example: 
 
public class customport : NodePort 
{ 
public override bool CanConnect() 
{ 
IPortInfo info = this.Info as IPortInfo; 
if ((info.InConnectors != null && info.InConnectors.Count() > 0)) 
{ 
return false; 
} 
return true; 
} 
} 
7. 
How can you disable the blue square animation when you try to create a connection in a port? 
Please override the RunTimeConnectionIndicator style template. Please follow the code example. 
 
Code Example: 
 
<Style TargetType="controls:RunTimeConnectionIndicator"> 
            <Setter Property="Width" Value="100"></Setter> 
            <Setter Property="Height" Value="100"></Setter> 
            <Setter Property="Template"> 
                <Setter.Value> 
                    <ControlTemplate TargetType="controls:RunTimeConnectionIndicator"/> 
                </Setter.Value> 
            </Setter> 
        </Style> 
8. 
How to remove/disable all of the node adorners, including rotation and gray points and position values 
We will able to remove/disable the node adoners, including rotation and gray points and position values by removing their specific Constraints in the SelectorConstraints. Please follow the code example below. 
 
Code Example: 
 
1.For Removing Tooltip: 
 
(diagram.SelectedItems as ISelector).SelectorConstraints &= ~SelectorConstraints.Tooltip; 
 
2.For Removing QuickCommands: 
 
(diagram.SelectedItems as ISelector).SelectorConstraints &= ~SelectorConstraints.QuickCommands; 
 
3.For Removing node adoner: 
 
(diagram.SelectedItems as ISelector).SelectorConstraints &= ~SelectorConstraints.Resizer; 
 
4.For Removing Rotator: 
 
(diagram.SelectedItems as ISelector).SelectorConstraints &= ~SelectorConstraints.Rotator; 
 
5.For Removing All of them: 
 
(diagram.SelectedItems as ISelector).SelectorConstraints &= ~SelectorConstraints.Default; 
 
 
 
9. 
Why are keyboard commands disabled? I cannot use del to remove a node or cntrl+c to copy nodes 
Keyboard interaction will work for diagram, only when it has keyboard focus. To bring keyboard focus to diagram, please use following code example. 
 
Code Example: 
 
diagram.PointerReleased += Diagram_PointerReleased; 
 
private void Diagram_PointerReleased(object sender, PointerRoutedEventArgs e) 
        { 
            e.Handled = true; 
        } 
 
Regards, 
 
Karkuvel Rajan.S 
 



DY Dylan April 7, 2018 06:01 PM UTC

Hi again,

I have more questions :/,

- I did not receive any update so the crash is still happening.
- Since I updated to last version the draw tool crash the diagram.
- I cannot control CustomPort as NodePort because it uses NodePortViewModel and if I change it, it crashes.
- Since im using NodeViewModel, is there any way I can detect a collision while moving an element? (OnPositionChanged?, Detect when OffsetX or OffsetY is the same as other element in the diagram and change the color to red to show the user there is a collision.)
- How can I center the diagram page (page in the center of the diagram and zoom 50%)
- Is there any way to create groups dynamically?
- What is the difference between NodePort, Node and NodeViewModel, NodePortViewModel? Is just that I cannot override methods?
- How can I disable a button until command.canExecute?
- How can I prevent dragging objects outside the diagram page?
- Sometimes, when you select items with the mouse, it does not select all of them, like It does not detect they are inside the bounds of the selection.

Thats all,
Thank you so much!


KR Karkuvel Rajan Shanmugavel Syncfusion Team April 9, 2018 12:26 PM UTC

Hi Dylan, 
 
Please find the response to your queries as below. 
 
S.No 
Query 
Response 
1.,2. 
I did not receive any update so the crash is still happening. 
 
Since I updated to last version the draw tool crash the diagram 
Reported issues are fixed in 2018 Vol2 SP1 (16.1.0.32v), please update to this version. 
3. 
I cannot control CustomPort as NodePort because it uses NodePortViewModel and if I change it, it crashes. 
We have created a sample based on your requirement please refer the sample link. 
 
 
4. 
Since im using NodeViewModel, is there any way I can detect a collision while moving an element? (OnPositionChanged?, Detect when OffsetX or OffsetY is the same as other element in the diagram and change the color to red to show the user there is a collision.) 
We have provided support to place a node without intersecting with other elements in the diagram. By using CollisionState and GetCollisionFreeLocation method, you can able to find a possible position without intersecting others for any given elements.We have provided code example and sample to achieve this. 
 
Code Example: 
 
(diagram.Info as IGraphInfo).SelectorChangedEvent += OnSelectorChangedEvent; 
 
private void OnSelectorChangedEvent(object sender, SelectorChangedEventArgs args) 
        { 
            if (args.Item is SelectorViewModel && args.NewValue.InteractionState == NodeChangedInteractionState.Dragged) 
            { 
                var selectorViewModel = (SelectorViewModel)args.Item; 
                if (selectorViewModel.Nodes is IEnumerable<object>) 
                { 
                    var selectedNodes = ((IEnumerable<object>)selectorViewModel.Nodes).ToList(); 
                    if (selectedNodes.Count == 1 && selectedNodes[0] is Node) 
                    { 
                        var selectedNode = (Node)selectedNodes[0]; 
                        var collisionState = new CollisionState() { Item = selectedNode }; 
                        ((IGraphInfo)this.diagram.Info).GetCollisionFreeLocation(collisionState); 
                        selectedNode.OffsetX = collisionState.Offset.X; 
                        selectedNode.OffsetY = collisionState.Offset.Y; 
                    } 
                } 
            } 
        } 
Where diagram is the instance of SfDiagram. 
 
 
 
Our Documentation process in UWP is not yet finished so we provide WPF link. All the API’s are same in both UWP and WPF. Please refer this for more details.  
5. 
How can I center the diagram page (page in the center of the diagram and zoom 50%) 
We have Fit To Page support for placing the diagram in the center of the ViewPort area. For larger diagram it works like ZoomOut the whole diagram and fit it into the ViewPort. For smaller diagram it works like fit the diagram in the center of the ViewPort, without zoomout. We can use margin values to give some space between diagram and viewport. 
 
Code Example: 
 
IGraphInfo graphinfo = diagramcontrol.Info as IGraphInfo 
 // To fit the Diagram into the view 
 graphinfo.Commands.FitToPage.Execute(null); 
 
We expect that Fit to page command will satisfy your requirement. If you need to center diagram specifically with 50% zoom, let know. There is no direct way of doing it, however we can check and provide you a solution. 
6. 
Is there any way to create groups dynamically? 
We have support to create groups dynamically by using Group and UnGroup Commands. For this we have to initialize the group collection in the diagram and then we have to select the elements that are wanted to be grouped the execute the Group command. We have provided Documentation link to Know about this. 
 
 
7. 
What is the difference between NodePort, Node and NodeViewModel, NodePortViewModel? Is just that I cannot override methods? 
Node , NodePort are the View classes (Control), which is rendered inside diagram control. Whereas NodeViewModel and NodePortViewModel are ViewModel objects of corresponding view. View and ViewModel is binded. You can use View or ViewModel, both will work. It is preferable to use ViewModel objects. 
8.,10. 
How can I disable a button until command.canExecute? 
 
Sometimes, when you select items with the mouse, it does not select all of them, like It does not detect they are inside the bounds of the selection. 
Please provide the proper details of your requirement. We are not able to get the requirement properly. Please provide Video or Screenshot for represent your requirement. 
9. 
How can I prevent dragging objects outside the diagram page? 
We have support to prevent the dragging objects outside he diagram page by set the DragLimit in ScrollSettings of SfDiagram as Diagram and also set Block as true in the SelectorChangedEvent. We have provided Code Example and Sample to achieve this requirement. 
 
Code Example 1: 
 
diagram.ScrollSettings.DragLimit |= ScrollLimit.Diagram; 
diagram.PageSettings.PageWidth = 1500; 
diagram.PageSettings.PageHeight = 750; 
(diagram.Info as IGraphInfo).SelectorChangedEvent += OnSelectorChangedEvent; 
 
Where diagram is the instance of the SfDiagram. 
 
Code Example 2: 
 
private void MainWindow_SelectorChangedEvent(object sender, SelectorChangedEventArgs args) 
        { 
            //Specific Criteria to be checked 
            if(Criteria == true) 
            { 
                args.Block = true; 
            } 
        } 
 
 
 
 
 
Regards, 
Karkuvel Rajan.S 
 


Loader.
Up arrow icon