Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0131: Auflistungen als Wrapper um Auflistungen

 von 

Beschreibung

Einige der Auflistungsklassen des Frameworks kann man auch als sogenannte Wrapper initialisieren, indem man im Konstruktor ein anderes Auflistungs-Objekt angibt. Als Wrapper halten diese Auflistungen selber keine Daten, sondern leiten alle Zugriffe lediglich auf die innere Liste um und fügen ihr spezifisches Verhalten hinzu. Die Kosten für solche Wrapper sind also vernachlässigbar. Wenn man sich nun die innere Liste merkt steht somit das Verhalten beider Auflistungs-Typen für die selben Daten zur Verfügung.

Schwierigkeitsgrad:

Schwierigkeitsgrad 1

Framework-Version(en):

.NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Compact Framework 1.0, .NET Compact Framework 2.0, .NET Framework 4

.NET-Version(en):

Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010

Download:

Download des Beispielprojektes [15,64 KB]

' Dieser Quellcode stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!

' Projektversion:   Visual Studio 2005
' Option Strict:    An
'
' Referenzen: 
'  - System
'  - System.Data
'  - System.Drawing
'  - System.Windows.Forms
'  - System.Xml
'
' Imports: 
'  - Microsoft.VisualBasic
'  - Microsoft.VisualBasic.ControlChars
'  - System
'  - System.Collections
'  - System.Collections.Generic
'  - System.Data
'  - System.Drawing
'  - System.Diagnostics
'  - System.Windows.Forms
'

' ##############################################################################
' ############################### ActionList.vb ################################
' ##############################################################################
''' <summary>
''' Auflistung mit benutzerdefiniertem Verhalten beim Löschen und Austauschen 
'''  von Elementen
''' </summary>
Public Class ActionList _
    : Inherits System.Collections.ObjectModel.Collection(Of DataClass)

    Public Sub New(ByVal data As IList(Of DataClass))
        MyBase.New(data)
    End Sub

    Protected Overrides Sub RemoveItem(ByVal index As Integer)
        MsgBox(String.Concat("Remove """, Me(index).Name, """"))
        MyBase.RemoveItem(index)
    End Sub

    Protected Overrides Sub SetItem(ByVal index As Integer, _
            ByVal item As DataClass)

        MsgBox(String.Concat("set """, Me(index).Name, _
            """ to """, item.Name, """"))
        MyBase.SetItem(index, item)
    End Sub

    Protected Overrides Sub InsertItem(ByVal index As Integer, _
            ByVal item As DataClass)

        MsgBox(String.Concat("insert """, item.Name, """ at ", index))
        MyBase.InsertItem(index, item)
    End Sub

End Class

' ##############################################################################
' ############################### DataClass.vb #################################
' ##############################################################################

Public Class DataClass

    Private _Name As String
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal newName As String)
            _Name = newName
        End Set
    End Property

    Public Sub New(ByVal name As String)
        _Name = name
    End Sub

End Class

' ##############################################################################
' ########################### frmNetAuflistungen.vb ############################
' ##############################################################################
Imports System.Collections.ObjectModel
Imports System.ComponentModel

Public Class frmNetAuflistungen

    Private _innerList As New List(Of DataClass)

    ' BindingList(Of T) feuert spezifische Events, die für DataBinding 
    '  erforderlich sind.
    Private _BindingList As New BindingList(Of DataClass)(_innerList)

    ' ReadOnlyCollection(Of T) ist nützlich, wenn man eine Auflistung nur mit 
    '  LeseZugriff offenlegen will. Die in dieser Anwendung ausgelösten 
    '  NotSupportedExceptions demonstrieren dieses
    Private _ReadonlyList As New ReadOnlyCollection(Of DataClass)(_innerList)

    ' Diese ActionList beerbt die Collection(Of DataClass). Dadurch kann sie 
    '  bei Hinzufügen, Löschen etc. benutzerdefinierte Aktionen auszuführen
    Private _ActionList As New ActionList(_innerList)

    'die verschiedenen Listen in ein Array stopfen
    Private _Sources() As IList(Of DataClass) = New IList(Of DataClass)() { _
       _innerList, _BindingList, _ReadonlyList, _ActionList}

    Private Sub frmNetAuflistungen_Load(ByVal sender As Object, _
            ByVal e As EventArgs) Handles MyBase.Load

        ReInit()

        ' Auswahl der Listen als Datasource des DatagridViews einrichten
        For Each lst As Object In _Sources
            cmbSelectSource.Items.Add(lst.GetType.Name)
        Next
        cmbSelectSource.SelectedIndex = 0
    End Sub

    Private Sub cmbSelectSource_SelectedIndexChanged(ByVal sender As Object, _
            ByVal e As EventArgs) Handles cmbSelectSource.SelectedIndexChanged

        BindingSource.DataSource = _Sources(cmbSelectSource.SelectedIndex)
    End Sub

    ' Helfer für die Sortierung
    Private Function CompareDataClass(ByVal x As DataClass, _
            ByVal y As DataClass) As Integer

        Return x.Name.CompareTo(y.Name)
    End Function

    Private Sub Button_Click(ByVal sender As Object, _
            ByVal e As EventArgs) Handles btInsert.Click, btRemove.Click, _
            btExchange.Click, btSort.Click, btReset.Click, btResetBinding.Click

        ' Die meisten der hier angebotenen Aktionen spiegeln sich erst dann im 
        '  DatagridView wieder, wenn ein ResetBinding erfolgt
        StatusLabel.Text = "ResetBinding erforderlich"
        Select Case True
            Case sender Is btReset
                ReInit()

            Case sender Is btSort
                ' Interessant am Wrapper-Prinzip ist, daß auf der inneren Liste 
                '  immer noch Operationen ausführbar sind, die der Wrapper 
                '  selbst nicht (mehr) unterstützt. Ich kann so also die 
                '  Elemente einer ReadOnlyCollection quasi "im Hintergrund" 
                '  sortieren, mit Auswirkung auch beim "Empfänger", dem solches 
                '  verwehrt ist (weil er keinen Zugriff auf die InnerList hat).
                '  Hingegen eine BindingList direkt zu sortieren wäre sehr 
                '  unperformant, da ja jede einzelne Änderung an die 
                '  angebundenen Controls gemeldet würde
                _innerList.Sort(AddressOf CompareDataClass)

            Case sender Is btResetBinding
                BindingSource.ResetBindings(False)
                StatusLabel.Text = ""

            Case Else
                If BindingSource.DataSource Is _BindingList Then _
                    StatusLabel.Text = ""

                Dim lst As IList(Of DataClass) = _
                   DirectCast(BindingSource.DataSource, IList(Of DataClass))
                Dim data As DataClass = lst(BindingSource.Position)
                Select Case True
                    Case sender Is btExchange
                        lst(BindingSource.Position) = _
                            New DataClass(data.Name & " " & lst.Count)

                    Case sender Is btRemove
                        lst.Remove(data)

                    Case sender Is btInsert
                        lst.Insert(BindingSource.Position, _
                            New DataClass("newItem" & lst.Count))
                End Select
        End Select
    End Sub

    Private Sub ReInit()
        Dim rnd As New Random(33)
        _innerList.Clear()
        For I As Integer = 0 To 15
            _innerList.Add(New DataClass("Data " & rnd.Next(0, 30)))
        Next
    End Sub

End Class

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.