0

問題はこれです、私は独自のイベントと2つのスタックを持つListViewを持っています

これらのイベントを処理するには、次のようなプロパティを有効にする必要があります。

Public property Enable_Something as boolean

ユーザー コントロールを UI に追加してプロパティを有効にしましたが、UI に同じコントロールをもう一度追加すると、両方のコントロールのイベントが処理されます。スタックは両方のコントロールによってプッシュ/ポップされます...

したがって、2 番目のコントロールが最初のコントロール スタックに何かを追加するため、プロパティが競合し、イベントとスタックも競合します。

各コントロールの操作/イベント/スタックを分離したいと考えています。

これは 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
4

1 に答える 1