VB.NET-Tipp 0131: Auflistungen als Wrapper um Auflistungen
von Spatzenkanonier
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: | 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: |
' 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.