Click here to Skip to main content
Licence CPOL
First Posted 6 Feb 2006
Views 89,969
Downloads 1,553
Bookmarked 55 times

How to Clone/Serialize/Copy & Paste a Windows Forms Control

By lxwde | 6 Feb 2006
Clone/Serialize/Copy & Paste a Windows Forms control through serializing its properties.
1 vote, 5.3%
1

2

3
1 vote, 5.3%
4
17 votes, 89.5%
5
5.00/5 - 19 votes
1 removed
μ 4.79, σa 1.65 [?]

Sample screenshot

Introduction

In the .NET environment, the System.Windows.Forms.Control class and all the concrete controls derived from it don’t have clone methods and they are not serializable. So there is no immediate way to clone, serialize, or copy & paste them.

This article presents an all-purpose approach to let you clone, serialize, or copy & paste a Windows Forms control through serializing its properties.

Background

Recently, I was doing some UI programming with C#. One problem I met is that I can not clone or copy & paste a Windows Forms control directly because the System.Windows.Forms.Control class is neither serializable nor does it have a Clone method. After searching the internet and reading James and Nish’s articles, Clipboard Handling with .NET (Part I, Part II), I came up with my own approach to copy & paste a Windows Forms control by serializing its properties.

Using the code

Using the code in the sample application to clone/serialize/copy & paste a Windows Forms control is very simple. The static methods to do serialization and deserialization are wrapped in the ControlFactory class.

Copy & Paste a control

...
//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

...
//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();

Implementation Details

When you clone/paste a control, the ControlFactory creates a new control through reflection, with the class name and namespace (partialName) passed to it.

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

If the new control is successfully created, ControlFactory then sets the properties of the new control with the property values it had retrieved from the original control.

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

In .NET clipboard programming, to create a custom format that uses a class, you must make the class serializable, that is it needs to have the Serializable attribute applied to it. CBFormCtrl is such a custom data format, it also uses a hash table to store the serializable properties.

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

Points of Interest

I’ve tested this approach with almost all the Windows Forms controls, it works fine with most of them. Unfortunately, when I copy & paste a ListView/ListBox/CheckedListBox or a TreeView, their item data will be lost, that is because the “Items” property of a ListView/ListBox/CheckedListBox and the “Node” property of a TreeView are not serializable.

To completely copy & paste these controls with their item data, you need to do some extra handling of the “Items” property or the “Node” property. As a reference, you can look at Tom John’s article to see how to fully serialize a TreeView control.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

lxwde

Software Developer

China China

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionHow ican clone a system Window? Pinmembermesiasrojo1:42 12 Aug '11  
QuestionActuall serialization is not working! PinmemberFadik4:07 15 Jul '09  
QuestionHow I can save/read controls to file? Pinmemberdrinkmaker12:43 21 Feb '09  
QuestionHow about the TabControl PinmemberSean_Miller10:39 19 Feb '09  
AnswerRe: How about the TabControl [modified] Pinmemberpataguillon3:48 21 Jul '09  
Here the code I added to manage TabControls cloning:
 
First, I created a new function to clone all controls for all pages:
public static Control CloneTabControl(TabControl origCtrl)
{
	TabControl oResult = new TabControl();
	foreach (TabPage page in origCtrl.TabPages)
	{
		TabPage newPage = new TabPage(page.Text);
		foreach (Control control in page.Controls)
		{
			Control ctrl = ControlFactory.CloneCtrl(control);
			newPage.Controls.Add(ctrl);
			ctrl.Show();
		}
		oResult.TabPages.Add(newPage);
	}
	return oResult;
}
 
Then, I changed the original code to get the TabControl in my new function like this :
public static Control CreateControl(string ctrlName,string partialName,Control original)
{
	try
	{
		Control ctrl;
		switch(ctrlName) 
		{				
			...
 
			case "TabControl":
				ctrl = CloneTabControl((TabControl)original);
				break;
		}		
		return ctrl; ...
	}
}
 
public static Control CloneCtrl(Control ctrl)
{
	...
	Control newCtrl = ControlFactory.CreateControl(cbCtrl.CtrlName,cbCtrl.PartialName,ctrl);
	...
}
 
public static Control GetCtrlFromClipBoard()
{
	...
	ctrl = ControlFactory.CreateControl(cbCtrl.CtrlName,cbCtrl.PartialName,null);
	...
}
 
Enjoy Wink | ;)
 
modified on Tuesday, July 21, 2009 9:03 AM

GeneralThank you very much it helped me a lot PinmemberSanShark1:20 6 Feb '09  
GeneralThank you Pinmemberhlmc21:24 29 Apr '08  
QuestionCopying data PinmemberAjmeri9:26 28 Feb '08  
GeneralJust Great Pinmembershapez3:58 22 Oct '07  
GeneralAssembly.LoadWithPartialName(string)' is obsolete Pinmembergajatko9:03 26 Aug '07  
GeneralSerializing Widows.Forms in C# PinmemberSakthiSurya21:24 29 Apr '07  
GeneralA Suggestion Pinmemberfonk66611:27 5 Feb '07  
QuestionAbout Events ? Pinmemberwhithix2:02 19 Sep '06  
AnswerRe: About Events ? Pinmemberlxwde21:23 19 Sep '06  
QuestionUsing this code with personalized controls. PinmemberDoXiGen6:10 29 Aug '06  
AnswerRe: Using this code with personalized controls. Pinmemberlxwde17:05 29 Aug '06  
AnswerRe: Using this code with personalized controls. PinmemberHotcut0:48 17 Oct '06  
GeneralSerialization thoughts ... PinmemberBillWoodruff18:46 13 Feb '06  
GeneralRe: Serialization thoughts ... Pinmemberlxwde3:24 14 Feb '06  
GeneralRe: Serialization thoughts ... PinmemberNigel Savidge8:17 2 Mar '06  
GeneralRe: Serialization thoughts ... PinmemberFrank Hileman3:08 7 Mar '06  
GeneralI wonder... PinmemberSuper Lloyd17:16 7 Feb '06  
GeneralRe: I wonder... Pinmemberlxwde17:37 7 Feb '06  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120210.1 | Last Updated 6 Feb 2006
Article Copyright 2006 by lxwde
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid