Copying/Cloning a control

G

Guest

Hi All,

I want to implement an 'generic' undo by placing a copy of a control in a
stack using System.Collections.Generic.Stack. Basically this way I don't need
to know if a user has edited text in tree, added or deleted a node etc,
added items to a list box etc etc. I just push the control onto the stack
when they change it (regardless of control type) and Pop if back if they undo.

My problem is how to a get a copy of the control? Obviosuly if I push the
control onto the stack, I get a reference to the original so every entry on
the stack is always the same, so I need to make a copy of the control that is
independant of the original.

Is there an *easy* way to do this - I've found a few examples, but they seem
dependant on knowing exactly what type of control it is, and wind through all
the properties etc, I was hoping for something more generic.

I am using VB.Net 2005.

Thanks in advance!
 
R

Robin Tucker

Hi Jon,

I don't think this idea is very good to be honest. There is a lot of
plumbing associated with a control that is just superfluous in an undo-redo
context - especially in a tree view where you are only interested in what
happened to the last node (i.e. subtree).

It's easy to create a structure for undo-redo where you do know precisely
what action occurred. Create a simple class hierarchy with overridable
method "Undo" and "Redo" - it's also useful to add in "CanUndo" and
"CanRedo", along with a "Size" and "Label" property (so you can know how
much space your undo-redo stack is taking up and can possibly tell the user
what the undo/redo action will do). Keep state information in the instance.
When the user deletes a node, you add a "NodeDeleted" class instance onto
your stack. When he inserts a node, you add a "NodeInserted" class
instance. Both of these are derived from your undo-redo base class.

Thestructure can be used in other contexts. For example if you are deleting
from a listview, where that node is also present in the tree, you still only
need the 1 undo-redo instance.



Robin
 
G

Guest

Just trying to help in the control cloning because I recently need it.
I developed the following function but at the end I didn't use it because I
changed my mind about cloning.

Private Function CloneControl(ByVal Ctrl As Control, ByVal Parent As
Object) As Control
Try
Dim CtrlType As Type = Ctrl.GetType()
Dim CtrlObject As Object = Activator.CreateInstance(CtrlType)
Dim CtrlNew As Control = CtrlObject

Dim pdcCtrl As
System.ComponentModel.PropertyDescriptorCollection =
System.ComponentModel.TypeDescriptor.GetProperties(Ctrl)
Dim pdcCtrlNew As
System.ComponentModel.PropertyDescriptorCollection =
System.ComponentModel.TypeDescriptor.GetProperties(CtrlNew)
For i As Integer = 0 To pdcCtrl.Count - 1
If pdcCtrl(i).Name = "Parent" Then
CtrlNew.Parent = Parent

ElseIf pdcCtrl(i).Name = "Controls" Then
If Not Ctrl.Controls Is Nothing Then
For Each CtrlChild As Control In Ctrl.Controls
CtrlNew.Controls.Add(CloneControl(CtrlChild,
CtrlNew))
Next
End If

Else
pdcCtrlNew(i).SetValue(CtrlNew, pdcCtrl(i).GetValue(Ctrl))
End If
Next

Return CtrlNew

Catch ex As Exception
Return Nothing
End Try
End Function

ex. calling the function:
Dim tb as TextBox
tb = CloneControl(TextBox1, Nothing)

Hope this helps!
 
G

Guest

Ruben,

Thanks for the response, but the following line just generates a an error (A
first chance exception of type 'System.ComponentModel.Win32Exception'
occurred in System.dll) repeatedly -

pdcCtrlNew(i).SetValue(CtrlNew, pdcCtrl(i).GetValue(Ctrl))

Think I'm going give up on the idea; just thought it would be a neat way of
implementing do/undo for any control.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top