Implement deep copy of WPF controls: serialization/deserialization

Source: Internet
Author: User

Today, debuglzq encountered this problem when performing the WPF drag summary. Baidu does not seem to have an authoritative answer to this problem, so I wrote this blog post.

What I want to do is to drag the control (rectangle) in a form to another container control and keep the original control.

To better clarify the problem, see the following code snippet:

void canvas1_Drop(object sender, DragEventArgs e){   IDataObject data = new DataObject();   data = e.Data;   if (data.GetDataPresent(typeof(Rectangle)))   {      Rectangle rect = new Rectangle();      rect = data.GetData(typeof(Rectangle)) as Rectangle;                      canvas1.Children.Add(rect);                   }}

The last line of code reports such an exception during running:

Specified element is already the logical child of another element. Disconnect it first

This is a control copy problem. To solve this problem, we can:

void canvas1_Drop(object sender, DragEventArgs e){   IDataObject data = new DataObject();   data = e.Data;   if (data.GetDataPresent(typeof(Rectangle)))   {      Rectangle rect = new Rectangle();      rect = data.GetData(typeof(Rectangle)) as Rectangle;
canvas2.Children.Remove(rect);// canvas1.Children.Add(rect); }}

The above code can eliminate this exception, but the dragged control is also gone. If the original rectangle is not retained, the problem will be solved. debuglzq does not need to write this blog to share with you.

Since the control cannot be obtained directly, how can this problem be solved?

The easy way to think of is to copy this control. But as you can see, the above replication method obviously does not work. It is a copy of the referenced object. It only copies one pointer, which is actually the same object.

Deep copy, okay:

A silly method is as follows:

if (data.GetDataPresent(typeof(Rectangle))) {    Rectangle dataobj = data.GetData(typeof(Rectangle)) as Rectangle;    Rectangle rect = new Rectangle();    rect.Height = dataobj.RenderSize.Height;    rect.Width = dataobj.RenderSize.Width;    rect.Fill = dataobj.Fill;    rect.Stroke = dataobj.Stroke;    rect.StrokeThickness = dataobj.StrokeThickness;    canvas1.Children.Add(rect);    rect.SetValue(Canvas.TopProperty, e.GetPosition(canvas1).Y);    rect.SetValue(Canvas.LeftProperty, e.GetPosition(canvas1).X); }

The problem is solved, but this code is obviously ugly! Unsightly ~ Although the results have been achieved, debuglzq is always confused about where there is a time bomb. Let's take a look at it again. Even if there is no problem, one rectangle will have to be so expensive, what if I have a for loop ?!
Therefore, this solution is not acceptable!

You can clone a control by first serializing it using XamlWriterAnd then create a new control by deserializing it using XamlReader.

English is good. There are a lot of things in Chinese, and they are all written in one sentence!

We can (deep) copy this control to adopt the serialization/deserialization method! The implementation is as follows:

If (data. getdatapresent (typeof (rectangle) {rectangle rect = new rectangle (); rect = data. getdata (typeof (rectangle) as rectangle; // canvas2.children. remove (rect); // canvas1.children. add (rect); // serialize control to deeply copy control !!!! String rectxaml = xamlwriter. save (rect); stringreader = new stringreader (rectxaml); xmlreader = xmlreader. create (stringreader); uielement clonedchild = (uielement) xamlreader. load (xmlreader); canvas1.children. add (clonedchild );}

Hope to help you ~

I haven't sent my blog post to the homepage for a long time. Let's send this post. The old bird flew over and patted me ~

TIPS: I saw a similar article in codeproject today,XAML serialization,I think it's not as good as mine. You can also take a look at it ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.