This is a migrated thread and some comments may be shown as answers.

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

10 Answers 124 Views
Diagram
This is a migrated thread and some comments may be shown as answers.
Aakansha
Top achievements
Rank 1
Aakansha asked on 12 Nov 2014, 09:58 AM
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. 

10 Answers, 1 is accepted

Sort by
0
Aakansha
Top achievements
Rank 1
answered on 14 Nov 2014, 06:55 AM
Can somebody from Admin reply to this thread?
0
Accepted
Zarko
Telerik team
answered on 14 Nov 2014, 02:18 PM
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.

 
0
Aakansha
Top achievements
Rank 1
answered on 17 Nov 2014, 12:52 PM
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?
 






0
Zarko
Telerik team
answered on 19 Nov 2014, 02:14 PM
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.

 
0
Aakansha
Top achievements
Rank 1
answered on 26 Nov 2014, 10:50 AM
Thanks. LayoutAsync and AutoFitAsync did the trick.
0
Aakansha
Top achievements
Rank 1
answered on 26 Nov 2014, 01:13 PM
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.
0
Zarko
Telerik team
answered on 26 Nov 2014, 06:30 PM
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.

 
0
Aakansha
Top achievements
Rank 1
answered on 26 Nov 2014, 07:34 PM
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.
0
Aakansha
Top achievements
Rank 1
answered on 26 Nov 2014, 07:38 PM
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()
0
Accepted
Zarko
Telerik team
answered on 27 Nov 2014, 11:24 AM
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.

 
Tags
Diagram
Asked by
Aakansha
Top achievements
Rank 1
Answers by
Aakansha
Top achievements
Rank 1
Zarko
Telerik team
Share this question
or