问题是这样的,我有一个 ListView 有自己的事件和两个堆栈
并且需要启用这样的属性来处理这些事件:
Public property Enable_Something as boolean
好吧,我将我的用户控件添加到 UI 并启用了该属性,但是如果我在 UI 中再添加一次相同的控件,那么两个控件的事件都会被处理!并且堆栈由两个控件推送/弹出...
所以属性发生冲突,事件和堆栈也发生冲突,因为第二个控件将一些东西添加到第一个控件堆栈中。
我想为每个控件分离操作/事件/堆栈。
这是 form1 类(阅读评论):
Public Class Form1
Friend WithEvents Undom As ListView_Elektro.UndoRedoManager
Private lvi As ListViewItem
Private Sub Test(sender As Object, e As EventArgs) Handles MyBase.Shown
' Enable undo manager in listview1 but not in listview2
' But no way, the undomanager is handled by both controls...
ListView_Elektro1.Enable_UndoRedo_Manager = True
ListView_Elektro2.Enable_UndoRedo_Manager = False
Undom = New ListView_Elektro.UndoRedoManager(ListView_Elektro1)
lvi = New ListViewItem("hello1")
ListView_Elektro1.AddItem(lvi)
lvi = New ListViewItem("hello2")
ListView_Elektro2.AddItem(lvi)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) _
Handles Button1.Click
Undom.UndoLastAction()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) _
Handles Button2.Click
Undom.RedoLastAction()
End Sub
Private Sub OnItemAdded() Handles ListView_Elektro1.ItemAdded
MsgBox("Item added")
' ( No way, both ListView_Elektro1.ItemAdded and ListView_Elektro2.ItemAdded are handled here... )
End Sub
End Class
这是用户控件的重要部分:
Public Class ListView_Elektro : Inherits ListView
''' <summary>
''' Enable or disble the Undo/Redo monitoring.
''' </summary>
Public Property Enable_UndoRedo_Manager As Boolean = False
Public Shared Event ItemAdded As EventHandler(Of ItemAddedEventArgs)
Public Class ItemAddedEventArgs : Inherits EventArgs
Public Property Item As ListViewItem
End Class
Public Function AddItem(ByVal Item As ListViewItem) As ListViewItem
MyBase.Items.Add(Item)
RaiseEvent ItemAdded(Me, New ItemAddedEventArgs With {.Item = Item})
Return Item
End Function
''' <summary>
''' Creates a Undo/Redo Action.
''' </summary>
Class ListView_Action
''' <summary>
''' Names the Undo/Redo Action.
''' </summary>
Property Name As String
''' <summary>
''' Points to a method to excecute.
''' </summary>
Property Operation As [Delegate]
''' <summary>
''' Method of the Undo/Redo operation.
''' </summary>
Property Method As UndoRedoManager.Method
''' <summary>
''' Data Array for the method to excecute.
''' </summary>
Property Data As ListViewItem
End Class
Public Class UndoRedoManager
Private WithEvents LV As ListView_Elektro
' Delegate to Add an Item for Undo/Redo operations.
Delegate Sub AddDelegate(item As ListViewItem)
' Delegate to Remove an Item for Undo/Redo operations.
Delegate Sub RemoveDelegate(item As ListViewItem)
' The Undo/Redo action.
Private action As ListView_Action = Nothing
' The operation.
Public Enum Operation As Short
Undo = 0
Redo = 1
End Enum
' The method for the Undo/Redo operation.
Public Enum Method As Short
Add = 0
Remove = 1
End Enum
''' <summary>
''' This event is raised after an Undo/Redo action is performed.
''' </summary>
Event UndoRedo_IsPerformed As EventHandler(Of UndoneRedoneEventArgs)
Class UndoneRedoneEventArgs : Inherits EventArgs
Public Property Operation As Operation
Public Property Method As Method
Public Property Item As ListViewItem
Public Property UndoStack As Stack(Of ListView_Action)
Public Property RedoStack As Stack(Of ListView_Action)
End Class
''' <summary>
''' This event is raised when Undo/Redo Stack size changed.
''' </summary>
Event UndoRedo_StackSizeChanged As EventHandler(Of StackSizeChangedEventArgs)
Class StackSizeChangedEventArgs : Inherits EventArgs
Public Property UndoStack As Stack(Of ListView_Action)
Public Property RedoStack As Stack(Of ListView_Action)
Public Property UndoStackIsEmpty As Boolean
Public Property RedoStackIsEmpty As Boolean
End Class
Public Sub New(ByVal ListView As ListView_Elektro)
LV = ListView
' MsgBox(LV.ToString)
End Sub
''' <summary>
''' Undo the last action.
''' </summary>
Sub UndoLastAction()
If LV.Undostack.Count = 0 Then Exit Sub ' Nothing to Undo.
LV.IsDoingUndo = True
action = LV.Undostack.Pop ' Get the Action from the Stack and remove it.
action.Operation.DynamicInvoke(action.Data) ' Invoke the undo Action.
LV.IsDoingUndo = False
Raise_UndoRedo_IsPerformed(Operation.Undo, action.Method, action.Data)
End Sub
''' <summary>
''' Redo the last action.
''' </summary>
Sub RedoLastAction()
If LV.Redostack.Count = 0 Then Exit Sub ' Nothing to Redo.
LV.IsDoingRedo = True
action = LV.Redostack.Pop() ' Get the Action from the Stack and remove it.
action.Operation.DynamicInvoke(action.Data) ' Invoke the redo Action.
LV.IsDoingRedo = False
Raise_UndoRedo_IsPerformed(Operation.Redo, action.Method, action.Data)
End Sub
' Raises the "UndoRedo_IsPerformed" Event
Private Sub Raise_UndoRedo_IsPerformed(ByVal Operation As Operation, _
ByVal Method As Method, _
ByVal Item As ListViewItem)
RaiseEvent UndoRedo_IsPerformed(Me, New UndoneRedoneEventArgs _
With {.Item = Item, _
.Method = Method, _
.Operation = Operation, _
.UndoStack = LV.Undostack, _
.RedoStack = LV.Redostack})
Raise_UndoRedo_StackSizeChanged()
End Sub
' Raises the "UndoRedo_IsPerformed" Event
Private Sub Raise_UndoRedo_StackSizeChanged()
RaiseEvent UndoRedo_StackSizeChanged(Me, New StackSizeChangedEventArgs _
With {.UndoStack = LV.Undostack, _
.RedoStack = LV.Redostack, _
.UndoStackIsEmpty = LV.Undostack.Count = 0, _
.RedoStackIsEmpty = LV.Redostack.Count = 0})
End Sub
' Reverses an Undo/Redo action
Private Function GetReverseAction(ByVal e As UndoneRedoneEventArgs) As ListView_Action
action = New ListView_Action
action.Name = e.Item.Text
action.Data = e.Item
action.Operation = If(e.Method = Method.Add, _
New RemoveDelegate(AddressOf LV.RemoveItem), _
New AddDelegate(AddressOf LV.AddItem))
action.Method = If(e.Method = Method.Add, _
Method.Remove, _
Method.Add)
Return action
End Function
' This handles when an Undo or Redo operation is performed.
Private Sub UndoneRedone(ByVal sender As Object, ByVal e As UndoneRedoneEventArgs) _
Handles Me.UndoRedo_IsPerformed
Select Case e.Operation
Case Operation.Undo
' Create a Redo Action for the undone action.
LV.Redostack.Push(GetReverseAction(e))
Case Operation.Redo
' Create a Undo Action for the redone action.
LV.Undostack.Push(GetReverseAction(e))
End Select
End Sub
' Monitors when an Item is added to create an Undo Operation.
Private Sub OnItemAdded(sender As Object, e As ItemAddedEventArgs) _
Handles LV.ItemAdded
If LV.Enable_UndoRedo_Manager _
AndAlso (Not LV.IsDoingUndo And Not LV.IsDoingRedo) Then
LV.Redostack.Clear()
' // Crate an Undo Action
action = New ListView_Action
action.Name = e.Item.Text
action.Operation = New RemoveDelegate(AddressOf LV.RemoveItem)
action.Data = e.Item
action.Method = Method.Remove
LV.Undostack.Push(action)
Raise_UndoRedo_StackSizeChanged()
End If
End Sub
' Monitors when an Item is removed to create an Undo Operation.
Private Sub OnItemRemoved(sender As Object, e As ItemRemovedEventArgs) _
Handles LV.ItemRemoved
If LV.Enable_UndoRedo_Manager _
AndAlso (Not LV.IsDoingUndo And Not LV.IsDoingRedo) Then
LV.Redostack.Clear()
' // Crate an Undo Action
action = New ListView_Action
action.Name = e.Item.Text
action.Operation = New AddDelegate(AddressOf LV.AddItem)
action.Data = e.Item
action.Method = Method.Add
LV.Undostack.Push(action)
Raise_UndoRedo_StackSizeChanged()
End If
End Sub
End Class
End Class