H
Hamilton Woods
I am attempting to copy a Windows Form Control. I can do this by manually
creating a control, Label2 = new Label, and then iterating through all of
the properties, copying from Label1 to Label2. A Mr. Jon Box, with Quilogy,
Inc., steered me to reflection for a possible mechanism to make this more
generic. I have a partial solution, but can't get all the way there. So I
am asking for help.
Windows Form Controls do not implement ICloneable or ISerializable, so I
can't write a control to disk and read it back in to another control, nor
can I do even a shallow copy. Bummer.
I am lazy, so I want to write a piece of code that I can REUSE. In a
perfect world, I would not even have to use a SELECT CASE statement to
determine the class of the original object that I am trying to copy. I
think I would not be the only person interested in said piece of code.
Here's what I sent Mr. Box this morning:
Jon,
A follow-up on yesterday's email. Based on your steering me to reflection,
here's what I have so far. You can create a form, place a Button on that
form, and paste the following two procedures into the code section.
This is the event handler for a Button.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim newButton As Button
Dim sourceButton As Button
sourceButton = CType(sender, Button) ' cast the source as its type
newButton = CType(CopyObject(sourceButton), Button) ' call the function
that does the copy
newButton.Top = sourceButton.Top + sourceButton.Height ' move the
newButton to a new location so we can see it
newButton.Visible = True ' make sure it is visible
AddHandler newButton.Click, AddressOf Me.Button1_Click ' allow
Button1_Click to handle newButton's Click event
Me.Controls.Add(newButton) ' add the newly created control to the
controls collection
newButton = Nothing
End Sub
The event handler calls CopyObject. CopyObject returns an object (Button)
whose properties are the same as the original.
Public Function CopyObject(ByVal obj As Object) As Object
Dim strObjType As String
'Dim strPropertyName As String
Dim srcPropertyArray As Reflection.PropertyInfo()
Dim srcPropertyElement As Reflection.PropertyInfo
Dim newObject As Object
strObjType = obj.GetType().Name
srcPropertyArray = obj.GetType().GetProperties() ' retrieve all
properties of source object
Select Case obj.GetType.Name ' I don't know another way of creating a
new object of a specific type.
Case "Label"
newObject = New Label()
Case "Button"
newObject = New Button()
Case "CASE for each Windows Forms Control"
End Select
For Each srcPropertyElement In srcPropertyArray ' iterate through the
list of properties
'strPropertyName = srcPropertyElement.Name
If srcPropertyElement.CanRead And srcPropertyElement.CanWrite Then ' if
the property can be read from and written to,
srcPropertyElement.SetValue(newObject, srcPropertyElement.GetValue(obj,
Nothing), Nothing) ' copy the value to the new object
End If
Next
Return newObject
End Function
I think the properties get copied, but the newly created control does not
show up on the form. I tried this with a Label control on which I paint a
wireframe using gdi+ and added the Paint event handler, but the Paint event
doesn't work properly. I get a Label which is white and it doesn't respond
to the click event. I don't know if I need to do anything to copy event or
method information from one object to another. I wouldn't think so. I'll
also post this to some usenet news groups to see if I get any response.
Thanks for your help,
Hamilton Woods
Accutrol, LLC
7500 S. Memorial Pkwy, 215-V
Huntsville, AL 35802
256-882-7433
(e-mail address removed)
creating a control, Label2 = new Label, and then iterating through all of
the properties, copying from Label1 to Label2. A Mr. Jon Box, with Quilogy,
Inc., steered me to reflection for a possible mechanism to make this more
generic. I have a partial solution, but can't get all the way there. So I
am asking for help.
Windows Form Controls do not implement ICloneable or ISerializable, so I
can't write a control to disk and read it back in to another control, nor
can I do even a shallow copy. Bummer.
I am lazy, so I want to write a piece of code that I can REUSE. In a
perfect world, I would not even have to use a SELECT CASE statement to
determine the class of the original object that I am trying to copy. I
think I would not be the only person interested in said piece of code.
Here's what I sent Mr. Box this morning:
Jon,
A follow-up on yesterday's email. Based on your steering me to reflection,
here's what I have so far. You can create a form, place a Button on that
form, and paste the following two procedures into the code section.
This is the event handler for a Button.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim newButton As Button
Dim sourceButton As Button
sourceButton = CType(sender, Button) ' cast the source as its type
newButton = CType(CopyObject(sourceButton), Button) ' call the function
that does the copy
newButton.Top = sourceButton.Top + sourceButton.Height ' move the
newButton to a new location so we can see it
newButton.Visible = True ' make sure it is visible
AddHandler newButton.Click, AddressOf Me.Button1_Click ' allow
Button1_Click to handle newButton's Click event
Me.Controls.Add(newButton) ' add the newly created control to the
controls collection
newButton = Nothing
End Sub
The event handler calls CopyObject. CopyObject returns an object (Button)
whose properties are the same as the original.
Public Function CopyObject(ByVal obj As Object) As Object
Dim strObjType As String
'Dim strPropertyName As String
Dim srcPropertyArray As Reflection.PropertyInfo()
Dim srcPropertyElement As Reflection.PropertyInfo
Dim newObject As Object
strObjType = obj.GetType().Name
srcPropertyArray = obj.GetType().GetProperties() ' retrieve all
properties of source object
Select Case obj.GetType.Name ' I don't know another way of creating a
new object of a specific type.
Case "Label"
newObject = New Label()
Case "Button"
newObject = New Button()
Case "CASE for each Windows Forms Control"
End Select
For Each srcPropertyElement In srcPropertyArray ' iterate through the
list of properties
'strPropertyName = srcPropertyElement.Name
If srcPropertyElement.CanRead And srcPropertyElement.CanWrite Then ' if
the property can be read from and written to,
srcPropertyElement.SetValue(newObject, srcPropertyElement.GetValue(obj,
Nothing), Nothing) ' copy the value to the new object
End If
Next
Return newObject
End Function
I think the properties get copied, but the newly created control does not
show up on the form. I tried this with a Label control on which I paint a
wireframe using gdi+ and added the Paint event handler, but the Paint event
doesn't work properly. I get a Label which is white and it doesn't respond
to the click event. I don't know if I need to do anything to copy event or
method information from one object to another. I wouldn't think so. I'll
also post this to some usenet news groups to see if I get any response.
Thanks for your help,
Hamilton Woods
Accutrol, LLC
7500 S. Memorial Pkwy, 215-V
Huntsville, AL 35802
256-882-7433
(e-mail address removed)