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

本文共 2624 字,大约阅读时间需要 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上看到一篇类似的文章,觉得写得没有我的好,大家也可以看下~

 

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

转载地址:http://fmzix.baihongyu.com/

你可能感兴趣的文章
Imperva开源域目录控制器,简化活动目录集成
查看>>
可观察性驱动开发,探索未知之地
查看>>
Webpack构建兼容IE8
查看>>
Deis发布1.4版本,支持Microsoft Azure
查看>>
用Elm语言降低失败的风险
查看>>
荷兰商业银行使用精益领导力推行改进
查看>>
cisco 多生成树MST笔记
查看>>
FPGA设计——图像处理(锐化增强)
查看>>
LINUX REDHAT第十三单元练习题
查看>>
Play Framework
查看>>
集合转数组注意
查看>>
gng3使用方法,正确的路由器防火墙安全配置方式
查看>>
基于域名虚拟主机及主站迁移
查看>>
linux sed
查看>>
elk之elasticsearch 入门
查看>>
C++11 thread
查看>>
云:虚拟之上的管理平台
查看>>
石墨烯+新能源:光伏领域应用潜力巨大
查看>>
本节书摘来自华章出版社《 自动化测试最佳实践:来自全球的经典自动化测试案例解析 》一 2.2 测试中的软件...
查看>>
2022 年 AI 会发展成什么样子,IBM 做出了 5 大预测
查看>>