Multi-select using Shift+Click

7 posts, 0 answers
  1. Peter
    Peter avatar
    11 posts
    Member since:
    Feb 2014

    Posted 03 Mar 2014 Link to this post

    Hello,

    I would like to add support to my RadDiagram for the user to perform a multi-select operation using the Shift key, in addition to the default Ctrl key.  I looked at adding to the InputBindings but there is no Command for select.  I also tried adding a handler for OnSelectionChanged that attempted to re-select the items in the SelectionChangedEventArgs.RemovedItems but my changes were apparently overridden after the handler completed and only the last clicked item would be selected.

    Is there a way to implement this?

    Thanks,

    Peter Pepperell
  2. Martin
    Admin
    Martin avatar
    1099 posts

    Posted 06 Mar 2014 Link to this post

    Hello Peter,

    As RadDiagram doesn't support this functionality out-of-the-box you can achieve your requirements with custom logic. You can handle the KeyDown, SelectionChanged and PreviewSelectionChanged events of the diagram.

    In the KeyDown handler you will need to check if the Shift and the left mouse button are down. If so, you can use the Diagram HitTestService to select the shape which is under the mouse and then select it with the SelectionService.SelectItem() method. Note that the second parameter of the SelectedItem() method controls if the item should be added in the current selected items collection. You can read more about the Diagram Services in our help.
    private HitTestService hitTestService;
    private SelectionService selectionService;
     
    public MainWindow()
    {
        InitializeComponent();
     
        this.AddHandler(RadDiagram.KeyDownEvent, new KeyEventHandler(OnKeyDown), true);
     
        hitTestService = this.diagram.ServiceLocator.GetService<IHitTestService>() as HitTestService;
        selectionService = this.diagram.ServiceLocator.GetService<ISelectionService<IDiagramItem>>() as SelectionService;
    }
    private void OnKeyDown(object sender, KeyEventArgs args)
    {
        bool isShiftKeyDown = (args.Key == Key.LeftShift || args.Key == Key.RightShift);
        bool isLeftMouseButtonDown = Mouse.LeftButton == MouseButtonState.Pressed;
     
        if (isShiftKeyDown && isLeftMouseButtonDown )
        {
            this.selectionService.SelectItem(this.hitTestService.ItemUnderMouse, true);
        }
    }

    The logic in the Diagram.PreviewSelectionChanged checks if the Shift key is down and if there are any items in the RemovedItems collection. If so, handle the event with e.Handled = true.
    private void diagram_PreviewSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        bool isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
        if (isShiftKeyDown && e.RemovedItems.Count != 0)
            e.Handled = true;
    }
     In the SelectionChanged  handle we get all shapes under the selection rectangle and select them one by one. This logic demonstrates how to select all the items in the selection rectangle bounds. But if you want to select only the clicked items you don't have to use it.

    private void diagram_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        bool isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
        if (isShiftKeyDown)
        {
            var shapes = hitTestService.GetShapesUnderRect(diagram.SelectionBounds);
     
            foreach (RadDiagramShape shape in shapes)
            {
                shape.IsSelected = true;
            }
        }
    }

    I attached a sample project with this implementation which you can use as a base for your requirements.

    Regards,
    Martin
    Telerik

    DevCraft Q1'14 is here! Join the free online conference to see how this release solves your top-5 .NET challenges. Reserve your seat now!

  3. UI for WPF is Visual Studio 2017 Ready
  4. Peter
    Peter avatar
    11 posts
    Member since:
    Feb 2014

    Posted 07 Mar 2014 in reply to Martin Link to this post

    Hi Martin,

    Thanks for the sample code, it works for my needs, but only to a point.  I want the Shift key to have the same behavior as the Ctrl key does, including deselecting individual items (when already selected) but leaving the remaining selected items unchanged.

    I made some changes to the sample you sent, but I was unable to achieve the desired result.  

    Can you show me what changes need to be made to your previous sample code to make the Shift+Click key combo mimic the behavior of the Ctrl+Click?

    Thanks,

    Peter
  5. Martin
    Admin
    Martin avatar
    1099 posts

    Posted 12 Mar 2014 Link to this post

    Hi Peter,

    In order to add this functionality you will need to do few changes in the last project that I send you. It seems that the KeyDown event is called too early that's why we should move our selection/deselection logic in the Diagram ShapeClick event handler and then made some changes. Here is an example in code:
    private void diagram_ShapeClicked(object sender, Telerik.Windows.Controls.Diagrams.ShapeRoutedEventArgs e)
    {
        bool isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
        if (isShiftKeyDown)
        {
            toolService.DeactivateTool(toolService.ToolList[0]);
            if (e.Shape.IsSelected)
            {
                this.selectionService.DeselectItem(e.Shape);
            }
            else
            {
                this.selectionService.SelectItem(e.Shape, true);
            }
        }
    }
     
    private void diagram_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        toolService.ActivateTool((toolService.ToolList[0] as ToolBase).Name);
    }

    Note that we are deactivating the PointerTool from the tools of the ToolService. Otherwise the selection will be triggered twice. Once for our custom selection and second time for the default selection. The PointerTool controls how the selection in the Diagram should be handled. After our custom selection we should activate this tool again in order for the default selection to work correctly. You can read more about the tools in the Tools Customization help article.

    I also attached an updated project with this implementation. I hope this is helpful. 

    Regards,
    Martin
    Telerik
     

    DevCraft Q1'14 is here! Watch the online conference to see how this release solves your top-5 .NET challenges. Watch on demand now.

     
  6. Douwe
    Douwe avatar
    10 posts
    Member since:
    Oct 2015

    Posted 14 Oct Link to this post

    I am also very interested in this functionality but unfortunately the attached sample project cannot be downloaded anymore; could this link be fixed?
  7. Douwe
    Douwe avatar
    10 posts
    Member since:
    Oct 2015

    Posted 14 Oct Link to this post

    Ok, I played around with the sample code above and came up with the following changes which seem to work just fine. The only thing which bothers me is that I made less changes then described above so I'm wondering if there are scenarios where my code will not work or have undesired side effects?

    In the previewSelectionChanged event handler I added an additional condition for the e.Handled to be set to True and this was needed to get the 'deselect' to work (when pressing the Shift key and clicking on a selected shape). 

     

    DiagramControl.PreviewSelectionChanged += DiagramControl_PreviewSelectionChanged;
    DiagramControl.ShapeClicked += DiagramControl_ShapeClicked;
     
    m_diagramSelectionService = DiagramControl.ServiceLocator.GetService<ISelectionService<IDiagramItem>>() as SelectionService;
     
    void DiagramControl_ShapeClicked(object sender, ShapeRoutedEventArgs e)
    {
        bool isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
     
        if (isShiftKeyDown)
        {
            if (e.Shape.IsSelected)
            {
                m_diagramSelectionService.DeselectItem(e.Shape);
            }
            else
            {
                m_diagramSelectionService.SelectItem(e.Shape, true);
            }
        }
    }
     
    void DiagramControl_PreviewSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        bool isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
     
        if (isShiftKeyDown && e.RemovedItems.Count != 0 && e.AddedItems.Count != 0)
        {
            e.Handled = true;
        }
    }
  8. Martin
    Admin
    Martin avatar
    1099 posts

    Posted 18 Oct Link to this post

    Hello Douwe,

    We had a technical issue with the attachments in the forum. The issue is already fixed so you should be able to download the .zip with the project. 

    About your implementation, well at first sight I cannot tell if you are going to experience any undesired effects. But as this is a custom solution I won't be surprised if it happens. This is why I recommend you test all expected scenarios.

    Regards,
    Martin
    Telerik by Progress
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
UI for WPF is Visual Studio 2017 Ready