Syncfusion:SfDiagram Node BackGround Color Dynamically Manipulation

Hi,

I am using Snynfusion SFdiagram  like this ;

        <Syncfusion:SfDiagram Grid.Column="1"
                              ItemAddedCommand="{Binding ItemAddedCommand}"
                              ItemDeletingCommand="{Binding ItemDeletingCommand}"
                              DropCommand="{Binding DropCommand}"
                              Nodes="{Binding Nodes}"
                              NodeChangedCommand="{Binding NodeChangedCommand}"
                              Connectors="{Binding Connectors}"
                              LayoutManager="{Binding LayoutManager}"
                              BridgeDirection="{Binding BridgeDirection}"
                              Constraints="{Binding Constraints}">
        </Syncfusion:SfDiagram>

and i have a setter for Node Background ;

 <Style TargetType="Syncfusion:Node">
                <Setter Property="ShapeStyle">
                    <Setter.Value>
                        <Style TargetType="Path">
                            <Setter Property="Fill"
                                    Value="Red" />
                            <Setter Property="Stretch"
                                    Value="Fill" />
                            <Setter Property="Stroke"
                                    Value="Black" />
                            <Setter Property="StrokeThickness"
                                    Value="1" />
                            <Setter Property="StrokeLineJoin"
                                    Value="Round" />
                            <Setter Property="StrokeStartLineCap"
                                    Value="Round" />
                            <Setter Property="StrokeEndLineCap"
                                    Value="Round" />
                            <Setter Property="StrokeDashCap"
                                    Value="Round" />
                        </Style>
                    </Setter.Value>
                </Setter>
            </Style>

CS file is like this ;

                     (args.Source as CustomNode).Annotations = new ObservableCollection<IAnnotation>()
                              {
                                 new AnnotationEditorViewModel()
                                 {
                                     Background = new SolidColorBrush(dtoColorMode.SelectedColor),

                                 }
                              };
                            LayoutManager.Layout.UpdateLayout();

When i try to update Background color with dtoColorMode.SelectedColor,  it does not change.



17 Replies 1 reply marked as answer

TT Tolga Tolga January 11, 2021 10:48 AM UTC

I Would Manage the Node like the below. I would dynamically manipulate of the node background color.




RA Ranjitha Amirthalingam Syncfusion Team January 11, 2021 11:07 AM UTC

Hi Tolga, 
 
Greetings from Syncfusion. 
 
Could you please confirm whether you want to update the background color when a node is tapped or you want to generate a diagram with nodes with different colors? 
 
Also, in your code, you are updating the background color for AnnotationEditorViewModel. Do you need to update the font color of the text? 
 
These details helps us to serve you better. 
 
Regards, 
Ranjitha A. 



TT Tolga Tolga January 11, 2021 11:23 AM UTC

Hi,

Actually i need all two option process because i am generating the node while application loading and after that i am adding a new node from the left menu. When I am adding the new node i would determine the node background color dynamically and each node can be different  background color.I dont need Node foreground or text back color. I would update node back ground color.


TT Tolga Tolga January 11, 2021 02:52 PM UTC

In addition  I also want to update background color of node dynamically when the property changed method performed. Therefore , I also need this during the creating node from .cs file , from component and property changed function triggered. You know i have a SFDiagram xaml file that i behave above. I need like this performing


RA Ranjitha Amirthalingam Syncfusion Team January 12, 2021 04:15 PM UTC

Hi Tolga, 
 
Requirement: Need to generate and update diagram with nodes with different colors. 
 
We have achieved your requirement using ContentTemplate property of NodeViewModel. We have provided sample to represent this. Please refer to the sample from the following link. 
 
 
Sample Details: 
In this sample, we have binded a custom property in the node template. And update the property (_Color) for the newly added datasource item. 
 
Regards, 
Ranjitha A. 


Marked as answer

TT Tolga Tolga January 13, 2021 07:15 AM UTC

Thanks for the respond.

I have also 1 question. As you know that i am using SFDiagram and i am createing node from the left menu to SFDiagram panel. When i am adding to the panel as a node, I want to understand that double click of clicked node understanding. For example i have 10 nodes, I want to understand spesific double click action of node and getting item  of double clicked action.


RA Ranjitha Amirthalingam Syncfusion Team January 13, 2021 08:45 AM UTC

Hi Tolga, 
 
We suspect that your requirement is “to get the Node details in the event when a node is double clicked”. The ItemDoubleTappedEvent of SfDiagram triggers when an element (node/connector) is double tapped. You can get the details of the node (which is doubletapped) in the event arguments of ItemDoubleTappedEvent. 
 
Code Example: 
(Diagram.Info as IGraphInfo).ItemDoubleTappedEvent += MainWindow_ItemDoubleTappedEvent; 
 
private void MainWindow_ItemDoubleTappedEvent(object sender, DiagramEventArgs args) 
 { 
    var argument = args as ItemDoubleTappedEventArgs; 
 
    // The node which is double tapped will be the Item of the ItemDoubleTappedEventArgs 
    var doubletappednode = argument.Item;         
 } 

 
For more details, please visit the below link. 
 
 
If we misunderstood your requirement, please explain us your requirement in detail. This helps us to serve you better. 
 
Regards, 
Ranjitha A. 



TT Tolga Tolga January 13, 2021 11:09 AM UTC

Hi,

DiagramVM is loading of form method. When i put it , Diagram.Info can not find inside of DiagramVM method.




TT Tolga Tolga January 13, 2021 11:41 AM UTC

Hi Again,
I put it in xaml as Name ="Diagram" and inside of DiagramVM i put it

            SfDiagram Diagram = new SfDiagram();


   <Syncfusion:SfDiagram Grid.Column="1"
                              x:Name="Diagram"
                              ItemAddedCommand="{Binding ItemAddedCommand}"
                              ItemDeletingCommand="{Binding ItemDeletingCommand}"
                              DropCommand="{Binding DropCommand}"
                              Nodes="{Binding Nodes}"
                              NodeChangedCommand="{Binding NodeChangedCommand}"
                              ItemSelectedCommand="{Binding SelectedItemCommand}"
                              Connectors="{Binding Connectors}"
                              LayoutManager="{Binding LayoutManager}"
                              BridgeDirection="{Binding BridgeDirection}"
                              Constraints="{Binding Constraints}">
        </Syncfusion:SfDiagram>




When I click double to node it does not work:







RA Ranjitha Amirthalingam Syncfusion Team January 13, 2021 03:27 PM UTC

Hi Tolga, 
 
 
We have analyzed the screenshot and found that you are trying to invoke event in ViewModel(DiagramViewModel) .Instead of using event, you can use ItemDoubleTappedCommand as like ItemAddedCommand,DropComand in viewmodel. And bind that command to view(SfDiagram). 
 
 
Regards, 
Ranjitha A. 



TT Tolga Tolga January 13, 2021 04:09 PM UTC

Hi,

I made it that you said. But it does not work. When i click the spesific node as double. OnItemDoubleTappedCommand method does not see the double command to node.

    Nodes = new ObservableCollection<CustomNode>();
            // Initialize Commands
            ItemAddedCommand = new Command(OnItemAdded);
            DropCommand = new Command(OnItemDrop);
            MenuItemClickedCommand = new Command(OnMenuItemClickedCommand);
            ItemDoubleTappedCommand = new Command(OnItemDoubleTappedCommand);
    
    <Syncfusion:SfDiagram Grid.Column="1"
                              x:Name="diagramm"
                              ItemAddedCommand="{Binding ItemAddedCommand}"
                              ItemDeletingCommand="{Binding ItemDeletingCommand}"
                              DropCommand="{Binding DropCommand}"
                              Nodes="{Binding Nodes}"
                              ItemDoubleTappedCommand="{Binding OnItemDoubleTappedCommand,Mode=TwoWay}"
                              ItemSelectedCommand="{Binding SelectedItemCommand}"
                              Connectors="{Binding Connectors}"
                              LayoutManager="{Binding LayoutManager}"
                              BridgeDirection="{Binding BridgeDirection}"
                              Constraints="{Binding Constraints}">
        </Syncfusion:SfDiagram>


TT Tolga Tolga January 13, 2021 07:06 PM UTC

I Could solve the problem. The binding was wrong but this time there is a error while i am updating selecting node . For example when the user double clicked a spesific node , I am opening new screen andchoose color. After this i am adding new node ;

You Can See the code and exception  ; 

        private void OnItemDoubleTappedCommand(object obj)
        {
            IList collection = (IList)Nodes;

            ItemDoubleTappedEventArgs args = obj as ItemDoubleTappedEventArgs;

            if (collection != null && collection.Count > 0)
            {
                if ((args.Item as CustomNode).ParentId != (int)NodeEnum.None)
                {
                    #region #if has a parent
                    (args.Item as CustomNode).Id = (args.Item as CustomNode).Id;
                    (args.Item as CustomNode).ID = (args.Item as CustomNode).Id;
                    (args.Item as CustomNode).ParentId = (args.Item as CustomNode).ParentId;


                    MessageBoxResult result = MessageBox.Show("Do you want to add a new node this window?",
                                                              "Color Confirmation",
                                                              MessageBoxButton.YesNo,
                                                              MessageBoxImage.Information);
                    if (result == MessageBoxResult.Yes)
                    {
                        MainWindow viewModel = new MainWindow();
                        ColorScreenWindow subWindow = new ColorScreenWindow();
                        subWindow.RaiseCustomEvent += new EventHandler(subWindow_RaiseCustomEvent);

                        subWindow.ShowDialog();
                        (args.Item as CustomNode).ColorOfNode = dtoColorMode.SelectedColor;
                    }


                    #region Setter Settings

                    Style style = new Style(typeof(Path));
                    style.Setters.Add(new Setter(Path.FillProperty, new SolidColorBrush(dtoColorMode.SelectedColor)));
                    style.Setters.Add(new Setter(Path.StrokeProperty, Brushes.Black));
                    style.Setters.Add(new Setter(Path.StrokeThicknessProperty, 2d));
                    style.Setters.Add(new Setter(Path.StrokeDashArrayProperty, new DoubleCollection() { 5 }));
                    style.Setters.Add(new Setter(Path.StretchProperty, Stretch.Fill));

                    (args.Item as CustomNode).ShapeStyle = style;

                    #endregion

                    CreateConnector((args.Item as CustomNode).ParentId, (args.Item as CustomNode).Id);

                    (Nodes as ObservableCollection).Remove(args.Item as CustomNode);
                    (Nodes as ObservableCollection).Add(args.Item as CustomNode);
                    LayoutManager.Layout.UpdateLayout();
                    #endregion
                }
            }
        }


error :
System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=Özel durum bir çağırma hedefi tarafından oluşturuldu.
  Source=mscorlib
  StackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Syncfusion.UI.Xaml.Diagram.Event`1.Publish(TEvent args)
   at Syncfusion.UI.Xaml.Diagram.GroupableWrapper.UpdateEditmode()
   at Syncfusion.UI.Xaml.Diagram.NodeWrapper.DoubleTap(Boolean fireEvent)
   at Syncfusion.UI.Xaml.Diagram.NodeWrapper.InvokeDoubleClick(MouseButtonEventArgs e)
   at Syncfusion.UI.Xaml.Diagram.Node.Node_MouseDoubleClick(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.Control.OnMouseDoubleClick(MouseButtonEventArgs e)
   at System.Windows.Controls.Control.HandleDoubleClick(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
 at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)



TT Tolga Tolga January 14, 2021 07:35 AM UTC

This was the most important part for me.

For example 14 nodes in Nodes. I want delete double clicked item after i am manipulating of it , i am adding again. Then i am taking this error.

How should I update the layout and Nodes in xaml binding in order to layout update process.



TT Tolga Tolga January 14, 2021 01:30 PM UTC

In addition, i would manipulate the data Nodes which is binded to SFDiagram. The problem is that manipulating of this Class is a problem. Layout can not bu updated. I am taking the null reference . You can see the code above and exception.


RA Ranjitha Amirthalingam Syncfusion Team January 14, 2021 02:22 PM UTC

Hi Tolga, 
 
We have analyzed the provided code and suspect that your requirement is to update the color for the double tapped node. We have prepared a sample to represent your requirement.  Please refer to the sample from the following link. 
 
Code Example: 
private void OnItemDoubleTappedCommand(object obj) 
        { 
            var args = obj as ItemDoubleTappedEventArgs; 
            if (args.Item is NodeViewModel) 
            { 
                ((args.Item as NodeViewModel).Content as Employee)._Color = "#FF808080";                
                this.LayoutManager.Layout.InvalidateLayout(); 
            } 
        } 


 
Sample Details: 
In this sample, we have created layout using DataSource (Employee class) .This class acts at the content of the NodeViewModel and have binded the content class property (_Color) to the ContentTemplate. 
 
For more information about layout, please visit the below link. 
 
 
If our assumption is different, please provide us more details regarding your requirement “why you are adding and removing the node with same id?” 
 
 
Regards, 
Ranjitha A. 



TT Tolga Tolga January 14, 2021 04:38 PM UTC

Thank you so much all of them worked. But i have also one question based on Nodes below xaml:

Nodes is normally object usage but i convert it to IList, after converting to IList , i can not conver to ToList().

Can you help this ?


        <Syncfusion:SfDiagram Grid.Column="1"
                              x:Name="diagramm"
                              ItemAddedCommand="{Binding ItemAddedCommand}"
                              ItemDeletingCommand="{Binding ItemDeletingCommand}"
                              DropCommand="{Binding DropCommand}"
                              Nodes="{Binding Nodes,Mode=TwoWay}"
                              ItemDoubleTappedCommand="{Binding Path= ItemDoubleTappedCommand}"
                              ItemSelectedCommand="{Binding SelectedItemCommand}"
                              Connectors="{Binding Connectors}"
                              LayoutManager="{Binding LayoutManager}"
                              BridgeDirection="{Binding BridgeDirection}"
                              Constraints="{Binding Constraints}">
        </Syncfusion:SfDiagram>


RA Ranjitha Amirthalingam Syncfusion Team January 15, 2021 09:22 AM UTC

Hi Tolga, 
 
If you want to cast Nodes(ObservableCollection<NodeViewModel>) to ToList() , you can directly cast to ToList() instead of casting it to IList .Since , we cannot directly cast IList to ToList() . We have provided code example to represent this. Please refer to the code example as below. 
 
Code Example: 
List<NodeViewModel> collection = (Nodes as NodeCollection).ToList(); 
 
Regards, 
Ranjitha A. 


Loader.
Up arrow icon