VB.NET: Was ist mit der Steuerung von Arrays passiert?

Das Weglassen von Steuerarrays in VB.NET ist eine Herausforderung für diejenigen, die über Arrays unterrichten.

  • Es ist nicht mehr möglich, ein Steuerelement wie ein Textfeld einfach zu kopieren und dann (ein- oder mehrmals) einzufügen, um ein Steuerelementarray zu erstellen.
  • Der VB.NET-Code zum Erstellen einer Struktur ähnlich einem Steuerungsarray war in allen Büchern über VB.NET, die ich gekauft und online gekauft habe, viel länger und viel komplexer. Es fehlt die Einfachheit der Codierung eines Steuerarrays, das in VB6 zu finden ist.

Wenn Sie auf die VB6-Kompatibilitätsbibliothek verweisen, befinden sich dort Objekte, die sich ähnlich wie Steuerarrays verhalten. Um zu sehen, was ich meine, verwenden Sie einfach den VB.NET-Upgrade-Assistenten mit einem Programm, das ein Steuerungsarray enthält. Der Code ist wieder hässlich, aber es funktioniert. Die schlechte Nachricht ist, dass Microsoft nicht garantiert, dass die Kompatibilitätskomponenten weiterhin unterstützt werden, und dass Sie sie nicht verwenden sollten.

instagram viewer

Der VB.NET-Code zum Erstellen und Verwenden von "Steuerungsarrays" ist viel länger und komplexer.

Laut Microsoft erfordert die Erstellung einer "einfachen Komponente, die die Funktionalität des Steuerungsarrays dupliziert", um etwas zu tun, das dem in VB 6 noch nahe kommt.

Sie benötigen sowohl eine neue Klasse als auch ein Hosting-Formular, um dies zu veranschaulichen. Die Klasse erstellt und zerstört tatsächlich neue Labels. Der vollständige Klassencode lautet wie folgt:

Öffentliche Klasse LabelArray
Erbt das System. Sammlungen. CollectionBase
Private ReadOnly HostForm As _
System. Windows. Formen. Bilden
Öffentliche Funktion AddNewLabel () _
Als System. Windows. Formen. Etikette
'Erstellen Sie eine neue Instanz der Label-Klasse.
Dim aLabel As New System. Windows. Formen. Etikette
'Fügen Sie das Etikett der Sammlung hinzu
'interne Liste.
Mir. Aufführen. Add (aLabel)
'Fügen Sie das Label zur Controls-Sammlung hinzu
'des Formulars, auf das das Feld HostForm verweist.
HostForm. Kontrollen. Add (aLabel)
'Legen Sie die Anfangseigenschaften für das Label-Objekt fest.
ein Etikett. Oben = Anzahl * 25
ein Etikett. Breite = 50
ein Etikett. Links = 140
ein Etikett. Tag = Ich. Anzahl
ein Etikett. Text = "Label" & ich. Anzahl. ToString
Geben Sie aLabel zurück
Endfunktion
Public Sub Neu (_
ByVal-Host als System. Windows. Formen. Bilden)
HostForm = Host
Mir. AddNewLabel ()
End Sub
Standardmäßige öffentliche ReadOnly-Eigenschaft _
Item (ByVal Index As Integer) As _
System. Windows. Formen. Etikette
Bekommen
CType (Me. List) zurückgeben. Artikel (Index), _
System. Windows. Formen. Etikette)
End Get
Endeigenschaft
Public Sub Remove ()
Stellen Sie sicher, dass ein Etikett entfernt werden muss.
Wenn ich. Count> 0 Dann
'Entfernen Sie das zuletzt dem Array hinzugefügte Label
'aus der Sammlung der Host-Formularsteuerelemente.
'Beachten Sie die Verwendung der Standardeigenschaft in
'Zugriff auf das Array.
HostForm. Kontrollen. Entfernen Sie (Me (Me. Count - 1))
Mir. Aufführen. RemoveAt (Me. Count - 1)
End If
End Sub
Klasse beenden

Um zu veranschaulichen, wie dieser Klassencode verwendet wird, können Sie ein Formular erstellen, das ihn aufruft. Sie müssten den unten gezeigten Code im Formular verwenden:

Öffentliche Klasse Form1. Erbt das System. Windows. Formen. Bilden. #Region "Von Windows Form Designer generierter Code" 'Außerdem müssen Sie die folgende Anweisung hinzufügen:' MyControlArray = New LabelArray (Me) 'nach dem Aufruf von InitializeComponent () in der. 'versteckter Regionalcode. 'Deklarieren Sie ein neues ButtonArray-Objekt. Dim MyControlArray As LabelArray. Private Sub btnLabelAdd_Click (_. ByVal Absender als System. Objekt, _. ByVal e As System. EventArgs) _. Behandelt btnLabelAdd. Klicken. 'Rufen Sie die AddNewLabel-Methode auf. 'von MyControlArray. MyControlArray. AddNewLabel () 'Ändern Sie die BackColor-Eigenschaft. 'des Knopfes 0. MyControlArray (0) .BackColor = _. System. Zeichnung. Farbe. Rot. End Sub. Private Sub btnLabelRemove_Click (_. ByVal Absender als System. Objekt, _. ByVal e As System. EventArgs) _. Behandelt btnLabelRemove. Klicken. 'Rufen Sie die Remove-Methode von MyControlArray auf. MyControlArray. Entfernen() End Sub. Klasse beenden

Erstens erledigt dies nicht einmal die Arbeit zur Entwurfszeit, wie wir es in VB 6 getan haben! Und zweitens befinden sie sich nicht in einem Array, sondern in einer VB.NET-Sammlung - eine ganz andere Sache als ein Array.

Der Grund, warum VB.NET das VB 6 "Control Array" nicht unterstützt, ist, dass es kein "Control" "Array" gibt (beachten Sie die Änderung der Anführungszeichen). VB 6 erstellt eine Sammlung hinter den Kulissen und lässt sie dem Entwickler als Array erscheinen. Aber es ist kein Array und Sie haben nur wenig Kontrolle darüber, abgesehen von den Funktionen, die durch die IDE bereitgestellt werden.

VB.NET hingegen nennt es das, was es ist: eine Sammlung von Objekten. Und sie geben dem Entwickler die Schlüssel zum Königreich, indem sie das Ganze direkt im Freien erstellen.

Als Beispiel für die Vorteile, die dies dem Entwickler bietet, mussten in VB 6 die Steuerelemente vom gleichen Typ sein und denselben Namen haben. Da dies nur Objekte in VB.NET sind, können Sie sie zu unterschiedlichen Typen machen und ihnen unterschiedliche Namen geben und sie dennoch in derselben Sammlung von Objekten verwalten.

In diesem Beispiel behandelt dasselbe Click-Ereignis zwei Schaltflächen und ein Kontrollkästchen und zeigt an, auf welche geklickt wurde. Machen Sie das in einer Codezeile mit VB 6!

Private Sub MixedControls_Click (_
ByVal Absender als System. Objekt, _
ByVal e As System. EventArgs) _
Behandelt Button1.Click, _
Button2.Click, _
CheckBox1.Click
'Die folgende Aussage muss eine lange Aussage sein!
»Hier stehen vier Zeilen, um es eng zu halten
genug, um auf eine Webseite zu passen
Label2.Text =
Microsoft. VisualBasic. Richtig (Absender. GetType. ToString,
Len (Absender. GetType. ToString) -
(InStr (Absender. GetType. ToString, "Formulare") + 5))
End Sub

Die Teilstring-Berechnung ist etwas komplex, aber es ist nicht wirklich das, worüber wir hier sprechen. Sie können im Click-Ereignis alles tun. Sie können beispielsweise den Typ des Steuerelements in einer If-Anweisung verwenden, um verschiedene Aktionen für verschiedene Steuerelemente auszuführen.

Franks Computing Studies Group Feedback zu Arrays

Franks Studiengruppe lieferte ein Beispiel mit einem Formular mit 4 Beschriftungen und 2 Schaltflächen. Knopf 1 löscht die Beschriftungen und Knopf 2 füllt sie. Es ist eine gute Idee, Franks ursprüngliche Frage noch einmal zu lesen und festzustellen, dass das von ihm verwendete Beispiel eine Schleife war, mit der die Caption-Eigenschaft eines Arrays von Label-Komponenten gelöscht wird. Hier ist das VB.NET-Äquivalent dieses VB 6-Codes. Dieser Code macht das, wonach Frank ursprünglich gefragt hat!

Öffentliche Klasse Form1. Erbt das System. Windows. Formen. Bilden. #Region "Von Windows Form Designer generierter Code" LabelArray (4) als Label dimmen. 'deklarieren ein Array von Labels. Private Sub Form1_Load (_. ByVal Absender als System. Objekt, _. ByVal e As System. EventArgs) _. Behandelt MyBase. Belastung. SetControlArray () End Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. End Sub. Private Sub Button1_Click (_. ByVal Absender als System. Objekt, _. ByVal e As System. EventArgs) _. Behandelt Button1.Click. 'Schaltfläche 1 Array löschen. Dim a As Integer. Für a = 1 bis 4. LabelArray (a) .Text = "" Nächster. End Sub. Private Sub Button2_Click (_. ByVal Absender als System. Objekt, _. ByVal e As System. EventArgs) _. Behandelt Button2.Click. 'Schaltfläche 2 Array füllen. Dim a As Integer. Für a = 1 bis 4. LabelArray (a) .Text = _. "Control Array" & CStr (a) Nächster. End Sub. Klasse beenden

Wenn Sie mit diesem Code experimentieren, werden Sie feststellen, dass Sie neben dem Festlegen der Eigenschaften der Beschriftungen auch Methoden aufrufen können. Warum habe ich (und Microsoft) mir die Mühe gemacht, den "hässlichen" Code in Teil I des Artikels zu erstellen?

Ich muss nicht zustimmen, dass es wirklich ein "Control Array" im klassischen VB-Sinne ist. Das VB 6 Control Array ist ein unterstützter Teil der VB 6-Syntax, nicht nur eine Technik. In der Tat kann dieses Beispiel möglicherweise so beschrieben werden, dass es sich um ein Array von Steuerelementen handelt, nicht um ein Steuerelementarray.

In Teil I habe ich mich beschwert, dass das Microsoft-Beispiel NUR zur Laufzeit und nicht zur Entwurfszeit funktioniert. Sie können Steuerelemente dynamisch zu einem Formular hinzufügen und daraus löschen, aber das Ganze muss in Code implementiert werden. Sie können Steuerelemente nicht wie in VB 6 per Drag & Drop erstellen. Dieses Beispiel funktioniert hauptsächlich zur Entwurfszeit und nicht zur Laufzeit. Sie können Steuerelemente zur Laufzeit nicht dynamisch hinzufügen und löschen. In gewisser Weise ist es das genaue Gegenteil des Beispiels von Teil I.

Das klassische Beispiel für ein VB 6-Steuerarray ist das gleiche, das im VB .NET-Code implementiert ist. Hier in VB 6 Code (dieser stammt von Mezick & Hillier, Visual Basic 6-Zertifizierungsprüfungshandbuch, S. 206 - leicht modifiziert, da das Beispiel im Buch zu nicht sichtbaren Steuerelementen führt):

Dim MyTextBox als VB.TextBox. Statische intNumber als Ganzzahl. intNumber = intNumber + 1. Setzen Sie MyTextBox = _. Mir. Kontrollen. Add ("VB.TextBox", _. "Text" & intNumber) MyTextBox. Text = MyTextBox. Name. MyTextBox. Sichtbar = Richtig. MyTextBox. Links = _. (intNumber - 1) * 1200

Aber wie Microsoft (und ich) zustimmen, sind VB 6-Steuerungsarrays in VB.NET nicht möglich. Das Beste, was Sie tun können, ist, die Funktionalität zu duplizieren. In meinem Artikel wurde die im Beispiel von Mezick & Hillier enthaltene Funktionalität dupliziert. Der Studiengruppencode dupliziert die Funktionalität, Eigenschaften und Aufrufmethoden festlegen zu können.

Das Fazit ist also, dass es wirklich davon abhängt, was Sie tun möchten. VB.NET hat noch nicht alles als Teil der Sprache zusammengefasst - aber letztendlich ist es weitaus flexibler.

John Fannons Übernahme von Kontroll-Arrays

John schrieb: Ich brauchte Kontroll-Arrays, weil ich zur Laufzeit eine einfache Zahlentabelle in ein Formular einfügen wollte. Ich wollte nicht die Übelkeit, sie alle einzeln zu platzieren, und ich wollte VB.NET verwenden. Microsoft bietet eine sehr detaillierte Lösung für ein einfaches Problem, aber es ist ein sehr großer Vorschlaghammer, um eine sehr kleine Nuss zu knacken. Nach einigen Experimenten fand ich schließlich eine Lösung. So habe ich es gemacht.

Das obige Beispiel zu Visual Basic zeigt, wie Sie eine TextBox in einem Formular erstellen können, indem Sie eine Instanz erstellen des Objekts, Festlegen von Eigenschaften und Hinzufügen zur Controls-Auflistung, die Teil des Formulars ist Objekt.

Dim txtDataShow As New TextBox
txtDataShow. Höhe = 19
txtDataShow. Breite = 80
txtDataShow. Ort = Neuer Punkt (X, Y)
Mir. Kontrollen. Hinzufügen (txtDataShow)
Obwohl die Microsoft-Lösung eine Klasse erstellt, bin ich zu dem Schluss gekommen, dass dies alles stattdessen in eine Unterroutine eingeschlossen werden kann. Jedes Mal, wenn Sie diese Unterroutine aufrufen, erstellen Sie eine neue Instanz des Textfelds im Formular. Hier ist der vollständige Code:

Öffentliche Klasse Form1
Erbt das System. Windows. Formen. Bilden

#Region "Von Windows Form Designer generierter Code"

Private Sub BtnStart_Click (_
ByVal Absender als System. Objekt, _
ByVal e As System. EventArgs) _
Behandelt btnStart. Klicken

Dim I As Integer
Dim sData As String
Für I = 1 bis 5
sData = CStr (I)
Rufen Sie AddDataShow auf (sData, I)
Nächster
End Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I As Integer)

Dim txtDataShow As New TextBox
Dim UserLft, UserTop As Integer
Dim X, Y als Ganzzahl
UserLft = 20
UserTop = 20
txtDataShow. Höhe = 19
txtDataShow. Breite = 25
txtDataShow. TextAlign = _
Horizontale Ausrichtung. Center
txtDataShow. BorderStyle = _
BorderStyle. FixedSingle
txtDataShow. Text = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Höhe
txtDataShow. Ort = Neuer Punkt (X, Y)
Mir. Kontrollen. Hinzufügen (txtDataShow)
End Sub
Klasse beenden
Sehr guter Punkt, John. Dies ist sicherlich viel einfacher als der Microsoft-Code... Ich frage mich also, warum sie darauf bestanden, es so zu machen.

Versuchen wir zu Beginn unserer Untersuchung, eine der Eigenschaftszuweisungen im Code zu ändern. Lass uns ändern

txtDataShow. Höhe = 19
zu

txtDataShow. Höhe = 100
Nur um sicherzustellen, dass es einen spürbaren Unterschied gibt.

Wenn wir den Code erneut ausführen, erhalten wir... Was??? ??? das gleiche. Überhaupt keine Änderung. Tatsächlich können Sie den Wert mit einer Anweisung wie MsgBox (txtDataShow) anzeigen. Höhe) und Sie erhalten immer noch 20 als Wert der Immobilie, unabhängig davon, was Sie ihr zuweisen. Warum passiert das?

Die Antwort ist, dass wir keine eigene Klasse ableiten, um die Objekte zu erstellen. Wir fügen lediglich Dinge zu einer anderen Klasse hinzu, sodass wir die Regeln der anderen Klasse befolgen müssen. Und diese Regeln besagen, dass Sie die Height-Eigenschaft nicht ändern können. (Wellllll... du kannst. Wenn Sie die Multiline-Eigenschaft in True ändern, können Sie die Höhe ändern.)

Warum VB.NET fortfährt und den Code ausführt, ohne auch nur zu wimmern, dass möglicherweise etwas nicht stimmt, wenn Ihre Aussage tatsächlich völlig außer Acht gelassen wird, ist ein ganz anderer Kritikpunkt. Ich könnte jedoch zumindest eine Warnung in der Kompilierung vorschlagen. (Hinweis! Hinweis! Hinweis! Hört Microsoft zu?)

Das Beispiel aus Teil I erbt von einer anderen Klasse, wodurch die Eigenschaften für den Code in der ererbenden Klasse verfügbar werden. Wenn Sie in diesem Beispiel die Height-Eigenschaft auf 100 ändern, erhalten Sie die erwarteten Ergebnisse. (Nochmal... Ein Haftungsausschluss: Wenn eine neue Instanz einer großen Label-Komponente erstellt wird, wird die alte verdeckt. Um die neuen Label-Komponenten tatsächlich zu sehen, müssen Sie den Methodenaufruf aLabel hinzufügen. Nach vorne bringen().)

Dieses einfache Beispiel zeigt, dass, obwohl wir einer anderen Klasse einfach Objekte hinzufügen KÖNNEN (und manchmal ist dies das Richtige), die Kontrolle über die Objekte programmiert wird erfordert, dass wir sie in einer Klasse ableiten und die am besten organisierte Art (ich wage zu sagen, "die .NET-Methode" ??) darin besteht, Eigenschaften und Methoden in der neuen abgeleiteten Klasse zu erstellen, um sie zu ändern Dinge. John blieb zunächst nicht überzeugt. Er sagte, dass sein neuer Ansatz seinem Zweck entspricht, obwohl es Einschränkungen gibt, nicht "COO" (Correctly Object Oriented) zu sein. In jüngerer Zeit schrieb John jedoch:

"... Nachdem ich zur Laufzeit einen Satz von 5 Textfeldern geschrieben hatte, wollte ich die Daten in einem nachfolgenden Teil des Programms aktualisieren - aber nichts änderte sich - die ursprünglichen Daten waren noch vorhanden.

Ich fand heraus, dass ich das Problem umgehen konnte, indem ich Code schrieb, um die alten Kisten abzunehmen und sie mit neuen Daten wieder zurückzusetzen. Ein besserer Weg wäre es, mich zu benutzen. Aktualisierung. Dieses Problem hat mich jedoch auf die Notwendigkeit aufmerksam gemacht, eine Methode zum Subtrahieren und Hinzufügen der Textfelder bereitzustellen. "

Johns Code verwendete eine globale Variable, um zu verfolgen, wie viele Steuerelemente dem Formular hinzugefügt wurden, also eine Methode ...

Private Sub Form1_Load (_
ByVal Absender als System. Objekt, _
ByVal e As System. EventArgs) _
Behandelt MyBase. Belastung
CntlCnt0 = Ich. Kontrollen. Anzahl
End Sub

Dann könnte die "letzte" Kontrolle entfernt werden ...

N = ich. Kontrollen. Anzahl - 1
Mir. Kontrollen. RemoveAt (N)
John bemerkte: "Vielleicht ist das etwas ungeschickt."

Auf diese Weise verfolgt Microsoft Objekte in COM UND in ihrem "hässlichen" Beispielcode oben.

Ich bin jetzt auf das Problem zurückgekehrt, Steuerelemente in einem Formular zur Laufzeit dynamisch zu erstellen, und habe mich erneut mit den Artikeln "Was ist mit Steuerelement-Arrays passiert" befasst.

Ich habe die Klassen erstellt und kann nun die Steuerelemente so auf dem Formular platzieren, wie ich es möchte.

John demonstrierte, wie die Platzierung von Steuerelementen in einem Gruppenfeld mithilfe der neuen Klassen gesteuert werden kann, die er verwendet hat. Vielleicht hatte Microsoft es doch richtig in ihrer "hässlichen" Lösung!