WPF控件深拷贝:序列化/反序列化
今天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的博文:总结.NET中的:赋值VS浅拷贝VS深拷贝[序列化/反序列化]
tips:今天在codeproject上看到一篇类似的文章,XAML Serialization,觉得写得没有我的好,大家也可以看下~
没什么高端的东西,老鸟绕过,轻拍~
WPF控件深拷贝:序列化/反序列化的更多相关文章
- [转载]WPF控件拖动
这篇博文总结下WPF中的拖动,文章内容主要包括: 1.拖动窗口 2.拖动控件 Using Visual Studio 2.1thumb控件 2.2Drag.Drop(不连续,没有中间动画) 2.3拖动 ...
- 浅尝辄止——使用ActiveX装载WPF控件
1 引言 使用VC编写的容器类编辑器,很多都可以挂接ActiveX控件,因为基于COM的ActiveX控件不仅封装性不错,还可以显示一些不错的界面图元. 但是随着技术不断的进步,已被抛弃的Active ...
- XMAL语法系列之-(2)---WPF控件继承图
WPF控件继承图 1 FrameworkElement 1.1 Panel(面板类元素) 1.1.1 Canvas 1.1.2 DockPanel 1.1.3 Grid 1.1.4 TabPanel ...
- 通过WinForm控件创建的WPF控件无法输入的问题
今天把写的一个WPF程序发布到别的机器上执行,发现一个比较奇怪的问题:在那个机器上用英文输入法无法输入数字,非要切换到中文输入法才行:但在我的机器上却是好好的. 最开始以为是输入法的问题,弄了好一阵子 ...
- WPF控件--利用Winform库中的NotifyIcon实现托盘小程序
WPF控件--NotifyIcon 运行界面如下所示: 图1 图2 代码很少,如下所示 ...
- (转)WPF控件开源资源
(转)WPF控件开源资源 Textbox Drag/Drop in WPFhttp://www.codeproject.com/Articles/42696/Textbox-Drag-Drop-in- ...
- WPF控件模板
引言:在进行WPF项目开发过程中,由于项目的需要,经常要对某个控件进行特殊的设定,其中就牵涉到模板的相关方面的内容.本文也是在自己进行项目开发过程中遇到控件模板设定时集中搜集资料后整理出来的,以供在以 ...
- 关于WinForm引用WPF窗体---在Winform窗体中使用WPF控件
项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...
- 我的WPF控件库——KAN.WPF.XCtrl(141105)
自己开发的WPF控件库,只是初版,有扩展的Button,TextBox,Window.详细参见前几篇博文. WPF自定义控件(一)——Button:http://www.cnblogs.com/Qin ...
随机推荐
- 【物理/数学】概念的理解 —— pivot、position
0. 基本释义 pivot: n. 枢轴:中心点:旋转运动 vt. 以-为中心旋转:把-置于枢轴上 vi. 在枢轴上转动:随-转移 adj. 枢轴的:关键的 position: n. 位置,方位:职位 ...
- 【codeforces 546C】Soldier and Cards
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- BFKit:对常用 UIButton,UIColor,UIDevice,UIFont ,UIImage 等开发类进行了扩展
BFKit对常用于开发的类进行了扩展,整合了多个常用的控件和开发所需要的功能,是一个通用性的类库.集成后可以帮助更快的App开发.有兴趣的同学可以看看哦. http://code4app.com/io ...
- Swift学习——Swift解释具体的基础(六)
Optionals 可选 可选(它似乎并不如此翻译)它适用于那些值这种情况可能是空的,有两种情况一个可选:存在值并等于x,要么值不存在. 选配的概念在OC和C里面并没有.在OC中最接近的概念就是 ...
- MySQL分区表使用方法
原文:MySQL分区表使用方法 1. 确认MySQL服务器是否支持分区表 命令: show plugins; 2. MySQL分区表的特点 在逻辑上为一个表,在物理上存储在多个文件中 HASH分区(H ...
- win10 支持默认把触摸提升鼠标事件 打开 Pointer 消息
原文:win10 支持默认把触摸提升鼠标事件 打开 Pointer 消息 在 WPF 经常需要重写一套触摸事件,没有UWP的Pointer那么好用. 如果一直都觉得 WPF 的触摸做的不好,或想解决 ...
- C#连接Oracle数据库乱码问题
C#连接Oracle数据库乱码问题 数据库连接之前,设置环境变量,如下 Environment.SetEnvironmentVariable("NLS_LANG", "A ...
- 使用ant对项目进行多渠道打包时遇到问题记录
1.打包成功后,打开apk时,会出现闪退的现象解决方法:1.配置好ant后,先把项目正常运行后,再打包,如有问题见第2步 2.找到项目中build.xml,然后右键,选择Run As - ...
- leveldb原理和使用
LevelDB是一个基于本地文件的存储引擎,非分布式存储引擎,原理基于BigTable(LSM文件树),无索引机制,存储条目为Key-value.适用于保存数据缓存.日志存储.高速缓存等应用,主要是避 ...
- jvm常用优化方案和方法
新生代 GC(Minor GC):指发生在新生代的垃圾收集动作,因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快. 老年代 GC(Major GC ...