博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF控件深拷贝:序列化/反序列化
阅读量:5325 次
发布时间:2019-06-14

本文共 2689 字,大约阅读时间需要 8 分钟。

今天DebugLZQ在做WPF拖动总结的时候,遇到了这个问题。baidu了下,貌似没有解决这个问题的权威答案,遂写下这篇博文。

我想做的事情是:拖动一个窗体内的控件(Rectangle)到另一个容器控件内,而保留原来的控件。

为了更好地把问题说清楚,请看如下代码片段:

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);                   }}

最后一行代码报告这样的运行时异常:

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

这是控件拷贝的问题。为了解决这个问题,我们可以这样:

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);                   }}

以上代码,是能消除这个异常,但是,被拖动的控件也没了。如果需求是不保留原来这个Rectangle,问题也就解决了,DebugLZQ也没有必要写这篇博文分享给各位。

既然控件直接拿过来行不通,那么这么解决呢?

容易想到的方法是复制这个控件。但是如你所见,上面的复制方法明显行不通,属于引用对象的拷贝,只拷贝了一个指针,其实是同一个对象。

深拷贝,好了:

傻x一点办法如下:

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); }

问题是解决了,但这种代码明显丑陋!不堪入目~虽然是效果上实现了,但总感觉其中哪里影藏着一个定时炸弹,DebugLZQ惶惶不可终日;再退一步讲,即使这样没有问题,但是1个rectangle就得如此大费周章,要是来个for循环怎么办?!

因此这种解决方法绝非可接受!

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

英文就是好,本来中文啰嗦一大堆的东西,一句话就写完了!

我们可以(深)拷贝这个控件采用序列化/反序列化的方式!实现如下:

if (data.GetDataPresent(typeof(Rectangle))){   Rectangle rect = new Rectangle();   rect = data.GetData(typeof(Rectangle)) as Rectangle;   //canvas2.Children.Remove(rect);   //canvas1.Children.Add(rect);   //序列化Control,以深复制Control!!!!   string rectXaml = XamlWriter.Save(rect);   StringReader stringReader = new StringReader(rectXaml);   XmlReader xmlReader = XmlReader.Create(stringReader);   UIElement clonedChild = (UIElement)XamlReader.Load(xmlReader);   canvas1.Children.Add(clonedChild);}

 希望对你有帮助~

 很久没有把博文发到首页了,这篇发一下吧,老鸟飞过,轻拍~

这篇博文说白了,就是序列化/反序列化。更一般的方法,请参考DebugLZQ的博文:

tips:今天在codeproject上看到一篇类似的文章,觉得写得没有我的好,大家也可以看下~

 

没什么高端的东西,老鸟绕过,轻拍~

转载于:https://www.cnblogs.com/DebugLZQ/archive/2013/05/06/3062409.html

你可能感兴趣的文章
freebsd 实现 tab 命令 补全 命令 提示
查看>>
struts1和struts2的区别
查看>>
函数之匿名函数
查看>>
shell习题第16题:查用户
查看>>
Redis常用命令
查看>>
2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)
查看>>
2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
查看>>
redis cluster 集群资料
查看>>
微软职位内部推荐-Sr. SE - Office incubation
查看>>
微软职位内部推荐-SOFTWARE ENGINEER II
查看>>
centos系统python2.7更新到3.5
查看>>
C#类与结构体究竟谁快——各种函数调用模式速度评测
查看>>
我到底要选择一种什么样的生活方式,度过这一辈子呢:人生自由与职业发展方向(下)...
查看>>
poj 题目分类
查看>>
windows 安装yaml支持和pytest支持等
查看>>
读书笔记:季羡林关于如何做研究学问的心得
查看>>
面向对象的优点
查看>>
套接口和I/O通信
查看>>
阿里巴巴面试之利用两个int值实现读写锁
查看>>
浅谈性能测试
查看>>