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!

Signature
Jon
Robin Tucker - 27 Apr 2007 10:34 GMT
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
ruben - 27 Apr 2007 20:24 GMT
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!
> Hi All,
>
[quoted text clipped - 16 lines]
>
> Thanks in advance!
Jon Ellis - 30 Apr 2007 08:14 GMT
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.

Signature
Jon
> 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
[quoted text clipped - 63 lines]
> >
> > Thanks in advance!
Cor Ligthert [MVP] - 30 Apr 2007 09:31 GMT
Jon,
Like Robin I don't think it is a good idea, however the only way I know how
to do it is serializing and deserializing.
http://www.vb-tips.com/dbpages.aspx?ID=7ffd296f-9e81-47e6-88dc-61641f5c8d9d
Cor
> Hi All,
>
[quoted text clipped - 22 lines]
>
> Thanks in advance!