Your code has at least two issues not related to the actual question. Let's fix two of them first:
You set all properties even those you should not set; most notably you should not touch the "WindowTarget"
property! It is for internal use only and messing with it will stop at least some controls from working. I found I couldn't check a CheckBox
, for example.
Your code only will create visible controls if the orginal TabPage
is also the current one. All controls on all other pages are invisible and if you try to clone any other TabPage
all control will be added just fine but remain invisible.
Let's add a filter :
if(entry.Name != "WindowTarget") entry.SetValue(cNew, val);
and make the new controls visible:
cNew.Visible = true;
tpNew.Controls.Add(cNew);
Note that this is a simplistic solution as it will also make those controls visible that were invisible originally. You could instead show the page you want to clone or make a list of invisible controls; with their names you could find the cloned counterparts..
The last issue is also important but goes beyond the question: The code only clones the controls directly on the page, not any neseted controls (like RadioButtons
in a GroupBox
!). To do so you would have to write a recursive version!
- Now for the actual question: How can you give the cloned controls their own behaviour?
After cloning all their properties they are like freshly added controls, i.e. they have no event handlers at all.
So you need to
- write new event handlers for the new controls' events
- hook them up
While this is not really hard there are quite a few problems..
We know the naming scheme and so we can know which controls we want to supply with events. The event names are free to choose but to hook them up we need to know which of the new controls we are dealing with..
Here is and example that hooks up the first clone of a Button cb_hello
with a Click
event:
if (cNew.Name == "cb_hello1") cNew.Click += buttonNew_Click;
The code in the event demonstrates more issues:
private void buttonNew_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
Console.WriteLine(btn.Name + " says hiho");
btn.Parent.Controls["panel41"].BackColor = Color.ForestGreen;
((RadioButton)btn.Parent.Controls["radioButton11"]).Checked = true;
}
While casting the sender
to Button
is quite normal we run into trouble when we try to access any of the controls we have just cloned:
Since they were dynamically created we can't access any of them with variables. Instead we need to use the TabPage
's Controls
collection to find them.
We can set BackColor
or any other property inherited from Control
but to set RadioButton.Checked
we need to cast to RadioButton
; and we need to access the control from the Controls
collection, for example by its Name
.
Once you upgrade to recursive cloning you will want to use Controls.Find(name, true)
to include the nested controls..
As you can see it can be done but it will take a little more effort than coding the original controls and the code feels somewhat fragile as we introduce hidden dependencies: All those references to the cloned names rely on the original names!
Final note: While the regular properiets get cloned, the data
and structure
containers do not, i.e. all Items
, ListViewItems
or Rows
, Columns
collections etc, etc are not cloned!