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
close icon

How prevent Id override when dropping an item from palette

Hi,

i've noticed that when i drag and drop an item from the symbol palette to the diagram
that the id will be modified and some random text gets added to the id.
Due the reason that i'm generating the ids by my own i'd like to prevent this.

I also noticed that the constructor for the item gets not called when i drop it to the diagram.
Which could be the reason for this behavior.

Regards
Manuel

14 Replies

NG Naganathan Ganesh Babu Syncfusion Team February 6, 2020 12:31 PM UTC

Hi Manuel, 
 
i've noticed that when i drag and drop an item from the symbol palette to the diagram
that the id will be modified and some random text gets added to the id.
 
Due the reason that i'm generating the ids by my own i'd like to prevent this. 
 
By default, the “Id” property is unique for all diagram elements such as nodes/connectors and it couldn’t be changed at run time.   
I also noticed that the constructor for the item gets not called when i drop it to the diagram. 
Which could be the reason for this behavior. 
 
When we drag and drop the item from palette onto the diagram, the constructor for that item will be called in the source level. Could you please share us more details such as exact scenario of an issue with the screenshot or video?  
 
Regards, 
 
Naganathan K G 



MA Manuel February 6, 2020 12:35 PM UTC

I ran into an other problem which is related here too.
I'm using c# classes for my shapes, all of them 
are inheriting from a base class (NodeBase) which inhertis 
from the DiagramNode class.

When i add the shapes in the OnInitialized call
i'm able to cast them to the NodeBase base class
and use them as expected.

    public abstract class IndexBase : ComponentBase
    {
        protected IndexBase()
        {
            this.Nodes = new ObservableCollection();
            this.Connectors = new ObservableCollection();

            this.SelectedItems = new DiagramSelectedItems 
            { 
                Constraints = SelectorConstraints.UserHandle,
                UserHandles = ShortcutExtensions.GetShortcutHandles()
            };
        }

        public Diagram Diagram { get; protected set; }
        public Palette Palette { get; protected set; }

        public string PaletteHeight { get; protected set; }
        public string PaletteWidth { get; protected set; }

        public ObservableCollection Nodes { get; protected set; }
        public ObservableCollection Connectors { get; protected set; }

        public DiagramSelectedItems SelectedItems { get; protected set; }

        protected override void OnInitialized()
        {
             ...
            var command = new CommandNode { Title = "Command", OffsetX = 460, OffsetY = 400 };
            this.Nodes.Add(command);
            ...

    public class CommandNode : NodeBase
    {
        public CommandNode()
            : this(Guid.NewGuid())
        { }

        public CommandNode(Guid id)
            : base(id, NodeType.Command)
        {
            base.Width = 120;
            base.Height = 120;
        }

        public override string Color => "#37aff9";
    }

    public abstract class NodeBase : DiagramNode
    {
     ....
    }

When i'm dropping them from the palette i'm getting a DiagramNode instance,
which can not be upcasted to my c# shape models.




MA Manuel February 6, 2020 12:49 PM UTC

Maybe also related is an other problem i've noticed.
When i try to add new custom nodes from events to my diagram
i'm getting a default shape and not the instance i have created. 
Which means the given sizes and styles are gone.      

< DiagramEvents OnUserHandleMouseDown="@this.OnApplyShortcut" >< /DiagramEvents >

        public async void OnApplyShortcut(UserHandleEventsArgs args)
        {
            this.Nodes.Add(new CommandNode());
        }

Basically it is the same code i'm running from OnInitialized()
where this does work.

        protected override void OnInitialized()
        {
             ...
            var command = new CommandNode { Title = "Command", OffsetX = 460, OffsetY = 400 };
            this.Nodes.Add(command);


MA Manuel February 6, 2020 01:01 PM UTC

One more sample of using my custom classes from the nodes collection

        public async Task OnSelectionChanged(IBlazorSelectionChangeEventArgs args)
        {
            if (args?.State != EventState.Changed) return;
            if (!args.NewValue.Nodes.Any()) return;

            // casting into my base class works only when i add them within OnInitialized event
            // it fails from the palette or when i manually add them later to the nodes collection
            
            var selectedNode = this.Diagram.SelectedItems.Nodes.FirstOrDefault() as NodeBase;
            if (selectedNode == null) return;

            // using the custom node type to set the UserHandles visible / invisible
            this.SelectedItems.UserHandles.ApplyShortcuts(selectedNode.Type);

            await Task.CompletedTask;
        }


NG Naganathan Ganesh Babu Syncfusion Team February 7, 2020 12:14 PM UTC

Hi Manuel, 
 
Sorry for the inconvenience caused. 
 
The diagram class could not be customized in the blazor. So only the constructor is not called for the custom class. Could you please provide us more details such as exact requirement in detail with screenshot. 
 
Regards, 
 
Naganathan K G 



MA Manuel February 7, 2020 01:22 PM UTC

Well, i'm writting all my code in the code behind classes (c#)
and not in the markup files. This is required for unit testing
and business rules i need to implement for my interactive moddelling tool.

I separated my classes in the following way:



In example the CommandNode class looks like:


and inhertis from the NodeBase class:



Each node class specifies it's type, style, dimensions and also generates the identifier.
As you can see, i'm adding the type of the node to the id which is
my current solution to validate the connectors, because not all nodes
are allowed to connect to each other.

On the other hand i'm subscribing to some diagram events (i.e. OnSelectionChanged) 
where i'd like to check what type of node the current select shape is.
In this case i'm casting the DiagramNode to my base class (NodeBase)
to access the Type property (Enum). Or for events like OnUserHandleMouseDown
to provide shortcuts that are able to create new type safe nodes and connectors at runtime.
Which does not work at the moment (see my other thread).

I also initializing the palette with my node class to drag and drop type safe
nodes to the diagram, which does not work at the moment too.

So, from my point of view this makes it much more comfortable 
to work with the anonym shapes and from C# perspective this should work well,
because the observable Node and Connector collections, that are bound to the Diagram, 
contains the correct instances (types). But from my experience
with this Diagram Component so far, there seems to be a wrapper available,
that translates my blazor side type safe implementation into something else.

And it seems to be, that the forth and backwards transformation between
the diagram component and my implementation loses information for some reason.

An other point for me for this implementation is, that each node type
has it's own microservice (backend) and the diagram is just a composition
of shorted informations from many services. I.e. each  node on the backend
contains much more details (properties) which will be editable on other views
in the frontend.




MA Manuel February 9, 2020 03:05 PM UTC

I had a look into the event DragEnter(IBlazorDragEnterEventArgs args)
which fires when i add a node or connector from the palette.

Here i've noticed that the inner node element is of type NodeModel
instead of type DiagramNode and the inner connector element
is of type ConnectorModel instead of type DiagramConnector.

Which seems to be the reason for the palette issue i got that the
wrong type is dropped to the diagram and also it does not allow me
to override this behavior by my own within the event by creating
a new correct instance.

This probably also explains why the instances i'm creating from the UserHandles
in the OnUserHandleMouseDown event losing there styles when i add them
to the oberservable collections for DiagramNodes and Connectors.

And why i'm getting a NullReference exception when i change a property
of a node from the observable nodes collection.

I'm fine with it when there is an additional abstraction layer for technical purpose,
but currently there seems to be a mix mode within the available api's i have access too
and the sync between these layers seems to be buggy.





NG Naganathan Ganesh Babu Syncfusion Team February 10, 2020 12:55 PM UTC

Hi Manuel, 

Currently we are validating your requirement and we will update you with more information on 11th February 2020. 

Regards, 

Naganathan K G 



NG Naganathan Ganesh Babu Syncfusion Team February 11, 2020 02:47 PM UTC

Hi Manuel, 

Each node class specifies it's type, style, dimensions and also generates the identifier. 
As you can see, i'm adding the type of the node to the id which is
my current solution to validate the connectors, because not all nodes
are allowed to connect to each other.
 
 
On the other hand i'm subscribing to some diagram events (i.e. OnSelectionChanged)  
where i'd like to check what type of node the current select shape is. 
In this case i'm casting the DiagramNode to my base class (NodeBase)
to access the Type property (Enum). Or for events like OnUserHandleMouseDown
to provide shortcuts that are able to create new type safe nodes and connectors at runtime.
 
Which does not work at the moment (see my other thread). 

We suggest you to use Node’s “AddInfo” property to set the node information on this property and also you can use that property to access the node in events.   

Code example: 

public void OnSelectionChange(IBlazorSelectionChangeEventArgs args) 
    { 
        if (args.NewValue != null && args.NewValue.Nodes.Count >= 0) 
        { 
            NodeModel node = args.NewValue.Nodes[0] as NodeModel; 
            Dictionary<string, object> addinfo = JsonConvert.DeserializeObject<Dictionary<string, object>>(node.AddInfo.ToString()); 
 
            CommandNode commandNode = null; 
 
            foreach(DiagramNode node1 in diagram.Nodes) 
            { 
                if(node1.Id.Contains(addinfo["id"].ToString())) 
                { 
                    commandNode = node1 as CommandNode; 
                    break; 
                } 
            } 
        } 
    } 
 
So, from my point of view this makes it much more comfortable  
to work with the anonym shapes and from C# perspective this should work well, 
because the observable Node and Connector collections, that are bound to the Diagram, 
 
contains the correct instances (types). But from my experience
with this Diagram Component so far, there seems to be a wrapper available,
that translates my blazor side type safe implementation into something else.
 
 
And it seems to be, that the forth and backwards transformation between
the diagram component and my implementation loses information for some reason.
 

To construct an interactive blazor component, JS was required so this is the optimal way to create a diagram like interactive components. So we could not say this as wrapper component.  


Regarding IBlazorDragEnterEventArgs args
We are able to reproduce the reported issue at our end and we have logged this as an issue with “Need to change evtargs node/conenctor type as DiagramNode/DiagramConnector in Blazor”. The fix for the issue will be included on our weekly nuget release which will be available on 24th February 2020. 


Regards, 

Naganathan K G 



MA Manuel February 23, 2020 11:15 AM UTC

Hi, is you suggested way to change the id using the AddInfo Serialization still required
when you change all events to the DiagramNode and DiagramConnector Types
instead of using the underlaying Model classes? From my understanding 
this should fix this issue generally.

I also noticed an other problem here which is maybe related to the different base types too.
I'd like to select a given node programmatically, so i call the Select method of the diagram
with one of my custom node classes. But i've noticed that the OnSelectionChanged Event
is not triggered for the new node i've passed to the Select method.

await this.Diagram.Select(myNode);

Task OnSelectionChanged(IBlazorSelectionChangeEventArgs args)
{ }


SK Suganthi Karuppannan Syncfusion Team February 24, 2020 12:56 PM UTC

Hi Manuel, 
 
We are validating your requirement and update you with more details on 26th February 2020. 
 
Regards  
Suganthi K. 



AR Aravind Ravi Syncfusion Team February 26, 2020 01:50 PM UTC

Hi Manuel,   
 
To select the node in the diagram using select method API pass the object parameters as Observable collection.  So that node gets selected in diagram and selection change event gets fired. Please find below code snippet for how to use the select API method 
 
await diagram.Select(new ObservableCollection<DiagramNode>() { diagram.Nodes[1] }, null); 
 
We have modified a sample for your requirement. Please find the sample in below link 
 
   
Regards,   
Aravind Ravi 




MA Manuel February 26, 2020 03:13 PM UTC

Thanks for your help. I tried this and it works for a short period of time,
but the node gets deselected after a few milliseconds.

I provided a sample for it here:

https://www.syncfusion.com/support/directtrac/incidents/267237




AR Aravind Ravi Syncfusion Team February 27, 2020 12:29 PM UTC

Hi Manuel, 
 
Okay, please follow up in the incident for further updates. 
 
Regards 
Aravind Ravi 


Loader.
Live Chat Icon For mobile
Up arrow icon