Cut, Copy and Paste for a node and its sub-children

11 posts, 2 answers
  1. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 12 Nov 2014 Link to this post

    Hello All,

    I want to implement Cut, Copy and Paste feature for the Mind Map demo available in Telerik UI for WPF. So suppose I want to copy a node and its attached sub-children and paste it as children of another node.

    Kindly help that how can I do this if I want to extend the Mind Map sample with this feature. 
  2. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 14 Nov 2014 in reply to Aakansha Link to this post

    Can somebody from Admin reply to this thread?
  3. UI for WPF is Visual Studio 2017 Ready
  4. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 14 Nov 2014 Link to this post

    Hi Aakansha,
    One of the ways to achieve this is to register command bindings for the Diagram's Copy and Paste commands and add some custom logic there:
    static Example()
    {
        var copyBinding = new CommandBinding(DiagramCommands.Copy, ExecuteCopy, CanExecuteCopy);
        var pasteBinding = new CommandBinding(DiagramCommands.Paste, ExecutePaste);
     
        CommandManager.RegisterClassCommandBinding(typeof(RadDiagram), copyBinding);
        CommandManager.RegisterClassCommandBinding(typeof(RadDiagram), pasteBinding);
    }
     
    private static void CanExecuteCopy(object sender, CanExecuteRoutedEventArgs e)
    {
        var diagram = sender as RadDiagram;
        if (diagram != null)
        {
            var allowCopy = diagram.SelectedItems.Select(i => diagram.ContainerGenerator.ContainerFromItem(i)).All(d => d.AllowCopy);
            e.CanExecute = diagram.SelectedItems.Count() > 0 && allowCopy;
        }
    }
     
    private static void ExecuteCopy(object sender, ExecutedRoutedEventArgs e)
    {
        var diagram = sender as MindmapDiagram;
        if (diagram != null)
        {
            diagram.MyCopy();
        }
    }
     
    private static void ExecutePaste(object sender, ExecutedRoutedEventArgs e)
    {
        var diagram = sender as MindmapDiagram;
        if (diagram != null)
        {
            diagram.MyPaste();
        }
    }
    Then in the diagram's custom methods you can handle the copy and paste with something like this:
    public void MyCopy()
    {
        var childToCopy = this.SelectedItem;
        if (childToCopy != null)
        {
            this.SelectionMode = Windows.Diagrams.Core.SelectionMode.Extended;
            var container = this.ContainerGenerator.ContainerFromItem(childToCopy) as RadDiagramShapeBase;
            if (container != null)
            {
                SelectChildren(container);
            }
     
            this.Copy();
            this.SelectionMode = Windows.Diagrams.Core.SelectionMode.Single;
            this.DeselectAll();
            this.SelectedItem = childToCopy;
        }
        else
        {
            this.Copy();
        }
    }
     
    private void SelectChildren(IShape container)
    {
        foreach (var connection in this.Connections.Where(c => c.Source == container))
        {
            var shape = connection.Target;
            connection.IsSelected = true;
            if (shape != null)
            {
                shape.IsSelected = true;
                SelectChildren(shape);
            }
        }
    }
     
    public void MyPaste()
    {
        var selected = this.SelectedItem as Node;
        if (selected != null)
        {
            this.ItemsChanged += this.OnDiagramItemsChanged;
        }
     
        this.Paste();
     
        if (this.pastedItem != null)
        {
            var observable = this.GraphSource as IObservableGraphSource;
            if (observable != null)
            {
                var link = observable.CreateLink(selected, this.pastedItem);
                observable.AddLink(link);
            }
        }
     
        this.DeselectAll();
        this.SelectedItem = selected;
        this.pastedItem = null;
    }
    I hope I was able to help you.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 17 Nov 2014 Link to this post

    Thanks. Now I have another doubt:
    Suppose I copied a sub-tree and pasted on another node. It got posted. But the bounds it take as 0,0 so all the nodes come on top of each other.
    To fix this, in my MyPaste() function, I called the same function which you have called in mind map diagram for layout. So my aim is to paste and by default layout in anyone layout so that nodes dnt appear on top of each other.
    settings.Roots.Add(this.diagram.ContainerGenerator.ContainerFromItem(this.maintViewModel.Source.Items.OfType<object>().ElementAt(0)) as IShape);
    this.diagram.Layout(LayoutType.Tree, settings);
    this.diagram.AutoFit();
     This works for the rest of the nodes which have not been touch. But the rest of the children of the node which is copied, still come on top of each other. Any fix for this?
     






  6. Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 19 Nov 2014 Link to this post

    Hi Aakansha,
    This is very strange and I wasn't able to reproduce it in our MindMap example but one possible way to fix it is to call the LayoutAsync method in the MyPaste in your MindMapDiagram:
    public void MyPaste()
    {
        var selected = this.SelectedItem as Node;
        if (selected != null)
        {
            this.ItemsChanged += this.OnDiagramItemsChanged;
        }
     
        this.Paste();
     
        if (this.pastedItem != null)
        {
            var observable = this.GraphSource as IObservableGraphSource;
            if (observable != null)
            {
                var link = observable.CreateLink(selected, this.pastedItem);
                observable.AddLink(link);
            }
     
            TreeLayoutSettings settings = new TreeLayoutSettings()
            {
                TreeLayoutType = TreeLayoutType.MindmapHorizontal,
            };
            settings.Roots.Add(this.ContainerGenerator.ContainerFromItem(this.Items.ElementAt(0)) as IShape);
            this.LayoutAsync(LayoutType.Tree, settings);
            this.AutoFitAsync(new Thickness(10));
        }
     
        this.DeselectAll();
        this.SelectedItem = selected;
        this.pastedItem = null;
    }
    I hope I was able to help you and if you need further assistance feel free to ask.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  7. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 26 Nov 2014 in reply to Zarko Link to this post

    Thanks. LayoutAsync and AutoFitAsync did the trick.
  8. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 26 Nov 2014 in reply to Zarko Link to this post

    LayoutAysnc and AutoFitAysnc solved in my problem when I am in my WPF application but when I get the image of this, the image is all broken.

    Any reason for this. I have attached an image as an example. This is happening after I copy and paste nodes, re-layout and take image of this. I get broken links. This doesnt happen if I havnt used copy and paste even for really large mind maps.
  9. Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 26 Nov 2014 Link to this post

    Hi Aakansha,
    This is very strange issue and I'd like to ask you how do you get the image ? I'm asking because I wasn't able to reproduce the problem using our built-in export to png/bmp - I'm attaching a sample pictures
    We're looking forward to hearing from you.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  10. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 26 Nov 2014 in reply to Zarko Link to this post

    Hi Zarko...thanks for the quick reply. I found out the issue. I had done a fix for not getting the selected node from WPF editor to image conversion. The fix which I had done was that I was reloading the image using Load() and getting xml of the mind map using Save(). Code is: 
    var xml = owner.diagram.Save();
     if (!string.IsNullOrEmpty(xml))
     {
         owner.diagram.Load(xml);
         owner.diagram.AutoFit();
     }
    Sorry for the wrong question earlier. My real question is how can I get image MindMapNodeNotSelected.png rather than MindMapNodeSelected.png inspite of user keeping the node selected on save while getting the image.
  11. Aakansha
    Aakansha avatar
    20 posts
    Member since:
    Sep 2014

    Posted 26 Nov 2014 in reply to Zarko Link to this post

    I also want to add that I have also tried this.diagram.DeselectAll() method but even after this my image still have the node which is selected by the user while using the method ExportToImage()
  12. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 27 Nov 2014 Link to this post

    Hello Aakansha,
    The DeselectAll() didn't work because you have to wait for the next layout pass so that the adorner is actually hidden (we change its visibility to Collapse but this need some time). The easiest way to do this is to use a dispatcher like that:
    this.diagram.DeselectAll();
    this.Dispatcher.BeginInvoke(new Action(() =>
    {
        this.diagram.Export("PNG");
    }));
    I hope I was able to help you.

    Regards,
    Zarko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top
UI for WPF is Visual Studio 2017 Ready