Handle position changed

11 posts, 0 answers
  1. Geoffrey
    Geoffrey avatar
    48 posts
    Member since:
    Mar 2013

    Posted 14 Mar 2013 Link to this post

    Hi,

    Is there a way to handle position changed (of RadDiagramShape) if the X or Y position is negative ?

    Thanks in advance,
    Geoffrey
  2. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 19 Mar 2013 Link to this post

    Hi Geoffrey,

    You can use the RadDiagram DraggingService to track the changes of a shape's position while dragging it. Please take a look at the Services article in our documentation to get a better understanding if the services exposed by the Diagramming Framework and how to access them.

    In your particular case, you can attach an event handler to the DraggingService Dragging event handler:
    xDiagram.ServiceLocator.GetService<IDraggingService>().Dragging += new EventHandler<PositionChangedEventArgs>(OnDiagramItemsDragging);
    and then handle it to get the dragged shape and track its new coordinates:
    void OnDiagramItemsDragging(object sender, PositionChangedEventArgs e)
    {
        var draggedItems = e.Items;
        if (e.Items.Count() > 0)
        {
            RadDiagramShape draggedShape = e.Items.FirstOrDefault() as RadDiagramShape;
     
            if (draggedShape.Position.X < 0 || draggedShape.Position.Y < 0)
            {
                xDiagram.Background = new SolidColorBrush(Colors.Wheat);
            }
            else xDiagram.Background = null;
        }
    }

    Please give this a try and let me know if it helps.

    Regards,
    Tina Stancheva
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. DevCraft banner
  4. Yann
    Yann avatar
    2 posts
    Member since:
    Feb 2011

    Posted 15 Aug 2014 in reply to Tina Stancheva Link to this post

    Hello,

    The event is generated when moving with mouse. But how to intercept the movement with the keyboard (ctrl + arrow)?

    Thank you in advance,
    Best regards,
    Yann
  5. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 19 Aug 2014 Link to this post

    Hi Yann,

    The diagram doesn't provide an event that is fired when you move a shape with the keyboard. However, you can listen for moving of items in the RadDiagram if you subscribe for its CommandExecuted event and check if the executed command has its Name property set to "Move Items". Here is an example in code:

    private void diagram_CommandExecuted(object sender, CommandRoutedEventArgs e)
    {
        if (e.Command.Name == "Move Items")
        {
            // execute your logic
        }
    }

    Please let me know if this helps.

    Regards,
    Martin
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  6. david
    david avatar
    5 posts
    Member since:
    Apr 2016

    Posted 25 Apr in reply to Martin Link to this post

    Hi Martin,

     

    I need to prevent moving some shapes outside a predefined area.

    Using the "how to restrict the draggable area" of the raddiagram documentation (http://docs.telerik.com/devtools/wpf/controls/raddiagram/howto/customize-dragging), I was able to restrict the dragging of the shapes to the area I wanted.

    BUT

    this applies only when moving the shapes with the mouse, as Yann pointed out. Which means that once I release the mouse and the shape is right on the edge of the area, I can move it with the keyboard OUTSIDE the area. This is what I would like to prevent

     

    I have tried using your suggestion, but the problem is that this event happens AFTER the items are moved. This would still be fine with me, since I could just move the shapes back, but the issue with this is that in this even manager I don't have access to the details of the command executed, namely: I do not know in which direction the shapes where moved, neiter the amount of pixels they where moved by.

     

    is there any other way I can prevent moving the shapes with the keyboard outside of a predefined area ?

  7. david
    david avatar
    5 posts
    Member since:
    Apr 2016

    Posted 25 Apr in reply to david Link to this post

    hi again,

     

    nevermind, I figured out a way to do what I wanted, even though it is kind of dirty :

    // if shape is moved out of the boundaries :

                        this.Diagram.Undo();
                        while (this.Diagram.UndoRedoService.RedoStack.Any())
                            this.Diagram.UndoRedoService.RemoveCommand(this.Diagram.UndoRedoService.RedoStack.Last());

     

    that being said, it would be great to have a way to override the default behavior of the "move item" command, because as it is right now, it looks kind of unfinished :-/ (the fact taht there is a way to restrict the dragging area but not the "nudging" area is kind of useless)

  8. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 27 Apr Link to this post

    Hello David,

    Thank you for sharing your solution with the forum community. 

    Another approach is to override the default nudge command and implement custom logic that checks if the nudge (move items) action is allowed.

    I also attached a small example that demonstrates an approach with a new command. Basically, you can replace the input bindings for the nudge command (Ctrl+Up, Ctrl+Down, Ctrl+Left, Ctrl+Right) with input bindings for a new custom command which will call the DiagramCommands.Nudge.Execute() in its OnExecute handler.
    public static class MyDiagramCommands
    {
        public static RoutedUICommand Nudge;
     
        static MyDiagramCommands()
        {
            Nudge = new RoutedUICommand("Moves the items", "Nudge", typeof(RadDiagram));
        }
    }

    private void ReplaceNudgeCommand()
    {
        var commandBinding = new CommandBinding(MyDiagramCommands.Nudge, OnNudgeExecute, OnCanNudgeExecute);
        CommandManager.RegisterClassCommandBinding(typeof(RadDiagram), commandBinding);   
     
        var rightKeyBinding = new KeyBinding(MyDiagramCommands.Nudge, new KeyGesture(Key.Right, ModifierKeys.Control));
        var leftKeyBinding = new KeyBinding(MyDiagramCommands.Nudge, new KeyGesture(Key.Left, ModifierKeys.Control));
        var upKeyBinding = new KeyBinding(MyDiagramCommands.Nudge, new KeyGesture(Key.Up, ModifierKeys.Control));
        var downKeyBinding = new KeyBinding(MyDiagramCommands.Nudge, new KeyGesture(Key.Down, ModifierKeys.Control));
        this.diagram.InputBindings.Add(rightKeyBinding);
        this.diagram.InputBindings.Add(leftKeyBinding);
        this.diagram.InputBindings.Add(upKeyBinding);
        this.diagram.InputBindings.Add(downKeyBinding);
    }
     
    private void OnCanNudgeExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }
     
    private void OnNudgeExecute(object sender, ExecutedRoutedEventArgs e)
    {
          (if the nudge is allowed)
          {
            DiagramCommands.Nudge.Execute("LeftSmall", this.diagram);           
              // note that you will need to call the command with different parameter based on the pressed key
              // The allow values are "Left", "Right", "Up", "Down". You can also specify the step in the parameter after the direction, ex: "Left:15px", "Left:Small".
          }
    }
    I hope this helps.

    Regards,
    Martin
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  9. david
    david avatar
    5 posts
    Member since:
    Apr 2016

    Posted 27 Apr in reply to Martin Link to this post

    Hi Martin,

     

    thanks for your answer. Your solution is way cleaner than mine and I'll definitely do that. That's actually what I tried to do at first, but without success, since I could not find a way to override the Nudge command. I was missing the whole keybindings part.

     

    PS : you should definitely add this to the telerik documentation, in the HowTo section! that's not trivial and pretty useful in my opinion

  10. david
    david avatar
    5 posts
    Member since:
    Apr 2016

    Posted 27 Apr in reply to david Link to this post

    Well, I really am having trouble with this...

     

    here is what I did, as a test :

    in xaml :

    <telerik:RadDiagram Name="Diagram"
                        Background="White"
                        IsEditable="False"
                        IsRotationEnabled="false"
                        IsConnectorsManipulationEnabled="False"
                        AllowCopy="False"
                        AllowCut="False"
                        AllowPaste="False"
                        AllowDrop="False"
                        ShapeStyleSelector="{StaticResource CustomShapeStyleSelector}"
                        CommandExecuted="Diagram_CommandExecuted">
        <telerik:RadDiagram.CommandBindings>
            <CommandBinding Command="telerik:DiagramCommands.Nudge" CanExecute="NudgeCommandCanExecute" Executed="NudgeCommandExecuted" />
        </telerik:RadDiagram.CommandBindings>
    </telerik:RadDiagram>

    then, in c# :

    private void NudgeCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = false;
    }
     
    private void NudgeCommandExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("hello!!!");
    }
     
    private void Diagram_CommandExecuted(object sender, CommandRoutedEventArgs e)
    {
                if (e.Command.Name == "Move Items")
                {
                   MessageBox.Show("Command Executed");

                }
    }

     

    since I put e.CanExecute in my NudgeCommandCanExecute, I am expecting the program to do nothing at All (no "Hello!!!" and no "Command Executed")

     

    but... I get the "Command Executed", and the item is moved in the diagram.

     

    If I set e.CanExecute = true, I get both the "Hello!!!" and the "Command Executed", which is as expected.

     

    Now, Why is the "e.canExecute = false" not taken FULLY into account ? I can see that It prevents the execution of NudgeCommandExecuted(), but it still allows the Diagram to do something with the items, since they are moved

    is there something I am missing here ?

  11. david
    david avatar
    5 posts
    Member since:
    Apr 2016

    Posted 27 Apr Link to this post

    Aaaaaand I'm back (sorry for spamming, I'd like to delete my previous posts but can't :-/)

    I managed to get everything going in the end. The issue was that I was binding Directly on the DiagramCommands.Nudge command. I thought I could be lazy on this one, but apparently, that was a very poor idea. so I created my own Nudge Command as you advised, got all the keybindings going and this achieves what I want.

    for those interested, it's a little bit more tedious than what I hoped:

    <telerik:RadDiagram Name="Diagram"
                        Background="White"
                        IsEditable="False"
                        IsRotationEnabled="false"
                        IsConnectorsManipulationEnabled="False"
                        AllowCopy="False"
                        AllowCut="False"
                        AllowPaste="False"
                        AllowDrop="False"
                        ShapeStyleSelector="{StaticResource CustomShapeStyleSelector}">
        <telerik:RadDiagram.CommandBindings>
            <CommandBinding Command="local:MyDiagramCommands.Nudge" CanExecute="NudgeCommandCanExecute" Executed="NudgeCommandExecuted" />
        </telerik:RadDiagram.CommandBindings>
        <telerik:RadDiagram.InputBindings>
            <KeyBinding Gesture="Control+Left" Command="local:MyDiagramCommands.Nudge" CommandParameter="Left" />
            <KeyBinding Gesture="Control+Right" Command="local:MyDiagramCommands.Nudge" CommandParameter="Right" />
            <KeyBinding Gesture="Control+Up" Command="local:MyDiagramCommands.Nudge" CommandParameter="Up" />
            <KeyBinding Gesture="Control+Down" Command="local:MyDiagramCommands.Nudge" CommandParameter="Down" />
            <KeyBinding Gesture="Control+Shift+Left" Command="local:MyDiagramCommands.Nudge" CommandParameter="Left;Large" />
            <KeyBinding Gesture="Control+Shift+Right" Command="local:MyDiagramCommands.Nudge" CommandParameter="Right;Large" />
            <KeyBinding Gesture="Control+Shift+Up" Command="local:MyDiagramCommands.Nudge" CommandParameter="Up;Large" />
            <KeyBinding Gesture="Control+Shift+Down" Command="local:MyDiagramCommands.Nudge" CommandParameter="Down;Large" />
        </telerik:RadDiagram.InputBindings>
    </telerik:RadDiagram>

    public static class MyDiagramCommands
    {
        public static RoutedUICommand Nudge;
     
        static MyDiagramCommands()
        {
            Nudge = new RoutedUICommand("Move Items", "Nudge", typeof(RadDiagram));
        }
    }

    and:

    public static class MyDiagramCommands
    {
        public static RoutedUICommand Nudge;
     
        static MyDiagramCommands()
        {
            Nudge = new RoutedUICommand("Move Items", "Nudge", typeof(RadDiagram));
        }
    }

    and:

    private void NudgeCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true; // or false depending on some stuff
    }
     
    private void NudgeCommandExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        DiagramCommands.Nudge.Execute(e.Parameter, this.Diagram);
    }

     

    all in all, not so bad, But I would be Reeeeeeally great to have the ability to restrict the NudgeArea just As it is possible to restrict the DragArea when dragging. Food for thoughts!

     

    thanks again,

  12. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 28 Apr Link to this post

    Hello Geoffrey,

    I am glad to hear that the suggested solution works for you. As for the approach you tried after this, actually you can make it work but there are few things that should keep in mind. So, you can register directly the DiagramCommands,Nudge command, but this won't completely override the command behavior already defined but it will add the new one. If the last registered command handler (behavior) can't be executed the framework will bubble to the previous one (which is the default diagram nudge action). This is why when you set the e.CanExecute to False, the default nudge is executed. In order to prevent this, after setting the e.CanExecute property to False, you can also set the e.Handled to True. This will prevent the command events from bubbling and the default logic won't be executed.
    private void NudgeCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = false;
        e.Handled = true;
    }
    Basically, if you want to make sure that the previously registered OnExecute handler of a specific RoutedUICommand is not called, you will need to set the Handled property of the OnCanExecute arguments to True.

    However, if you completely override the Nudge command you will need to write its logic from scratch. Calling the DiagramCommands.Nudge.Execute() method in the OnExecute handler will gets you into an endless recursion. I gave you the approach from my last reply so you won't need to write the whole nudge from the beginning.

    I hope this information is useful.

    Regards,
    Martin
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
DevCraft banner