65.9K
CodeProject 正在变化。 阅读更多。
Home

如何克隆/序列化/复制和粘贴 Windows Forms 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (24投票s)

2006 年 2 月 6 日

CPOL

2分钟阅读

viewsIcon

248940

downloadIcon

8642

通过序列化其属性来克隆/序列化/复制和粘贴 Windows Forms 控件。

Sample screenshot

引言

在 .NET 环境中,System.Windows.Forms.Control 类及其派生的所有具体控件都没有克隆方法,并且它们不可序列化。因此,没有直接的方法来克隆、序列化或复制和粘贴它们。

本文介绍了一种通用方法,让您可以通过序列化其属性来克隆、序列化或复制和粘贴 Windows Forms 控件。

背景

最近,我用 C# 做了一些 UI 编程。我遇到的一个问题是我无法直接克隆或复制和粘贴 Windows Forms 控件,因为 System.Windows.Forms.Control 类既不可序列化,也没有 Clone 方法。在搜索互联网并阅读 James 和 Nish 的文章《使用 .NET 处理剪贴板》(第一部分第二部分)后,我提出了我自己的方法,通过序列化其属性来复制和粘贴 Windows Forms 控件。

使用代码

使用示例应用程序中的代码来克隆/序列化/复制和粘贴 Windows Forms 控件非常简单。用于进行序列化和反序列化的静态方法被封装在 ControlFactory 类中。

复制并粘贴控件

...
//copy a control to clipboard

ControlFactory.CopyCtrl2ClipBoard(this.comboBox1);
...

//then get it from clipboard and add it to its parent form

Control ctrl = ControlFactory.GetCtrlFromClipBoard();

this.Controls.Add(ctrl);
ctrl.Text = "created by copy&paste";
ctrl.SetBounds(ctrl.Bounds.X,ctrl.Bounds.Y+100, 
               ctrl.Bounds.Width,ctrl.Bounds.Height);
ctrl.Show();

克隆控件

...
//clone a control directly and then add it to its parent form

Control ctrl = ControlFactory.CloneCtrl(this.comboBox1);

this.Controls.Add(ctrl);
ctrl.Text = "created by clone";
ctrl.SetBounds(ctrl.Bounds.X,ctrl.Bounds.Y+350, 
               ctrl.Bounds.Width,ctrl.Bounds.Height);
ctrl.Show();

实现细节

当您克隆/粘贴控件时,ControlFactory 通过反射创建一个新控件,并传入它的类名和命名空间 (partialName)。

//
...
Assembly controlAsm = Assembly.LoadWithPartialName(partialName);
Type controlType = controlAsm.GetType(partialName + "." + ctrlName);
ctrl = (Control)Activator.CreateInstance(controlType);
...
return ctrl;

如果新控件创建成功,ControlFactory 然后使用它从原始控件中检索到的属性值设置新控件的属性。

public static void SetControlProperties(Control ctrl,Hashtable propertyList)
{
       PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(ctrl);

       foreach (PropertyDescriptor myProperty in properties)
       {
              if(propertyList.Contains(myProperty.Name))
              {
                    Object obj = propertyList[myProperty.Name];
                    myProperty.SetValue(ctrl,obj);
              }
              //...
       }
}

在 .NET 剪贴板编程中,要创建一个使用类的自定义格式,您必须使该类可序列化,也就是说,它需要应用 Serializable 属性。CBFormCtrl 是这样一个自定义数据格式,它还使用哈希表来存储可序列化的属性。

//
[Serializable()]
public class CBFormCtrl//clipboard form control
{
       private static DataFormats.Format format;
       private string ctrlName;
       private string partialName;
       private Hashtable propertyList = new Hashtable();
       //
       ...
}

关注点

我用几乎所有 Windows Forms 控件测试了这种方法,它对它们中的大多数都有效。不幸的是,当我复制和粘贴 ListView/ListBox/CheckedListBoxTreeView 时,它们的项目数据将会丢失,这是因为 ListView/ListBox/CheckedListBox 的 “Items” 属性和 TreeView 的 “Node” 属性不可序列化。

要完全复制和粘贴这些控件及其项目数据,您需要对“Items”属性或“Node”属性进行一些额外的处理。作为参考,您可以查看 Tom John 的文章,了解如何完全序列化 TreeView 控件。

© . All rights reserved.