VB.NET: Wat is er gebeurd met Arrays

Het weglaten van controle-arrays uit VB.NET is een uitdaging voor degenen die lesgeven over arrays.

  • Het is niet langer mogelijk om een ​​besturingselement, zoals een tekstvak, eenvoudig te kopiëren en vervolgens (een of meerdere keren) te plakken om een ​​besturingsarray te maken.
  • De VB.NET-code voor het maken van een structuur die lijkt op een controlearray is, in alle boeken op VB.NET die ik heb gekocht en online, veel langer en veel complexer. Het mist de eenvoud van het coderen van een controlearray die te vinden is in VB6.

Als u verwijst naar de VB6-compatibiliteitsbibliotheek, zijn er objecten die ongeveer hetzelfde werken als controlearrays. Om te zien wat ik bedoel, gebruikt u gewoon de VB.NET-upgradewizard met een programma dat een controlearray bevat. De code is weer lelijk, maar het werkt. Het slechte nieuws is dat Microsoft niet kan garanderen dat de compatibiliteitscomponenten blijven worden ondersteund en dat het niet de bedoeling is dat u ze gebruikt.

De VB.NET-code voor het maken en gebruiken van "control-arrays" is veel langer en veel complexer.

instagram viewer

Om iets te doen dat zelfs maar in de buurt komt van wat je in VB 6 kunt doen, moet volgens Microsoft een 'eenvoudig onderdeel worden gemaakt dat de functionaliteit van de controlearray dupliceert'.

Je hebt zowel een nieuwe klasse als een hostingformulier nodig om dit te illustreren. De klasse maakt en vernietigt eigenlijk nieuwe labels. De volledige klassecode is als volgt:

Openbare klasse LabelArray
Erft systeem. Collecties. CollectionBase
Privé ReadOnly HostForm als _
Systeem. Ramen. Formulieren. Het formulier
Openbare functie AddNewLabel () _
Als systeem. Ramen. Formulieren. Etiket
'Maak een nieuw exemplaar van de klasse Label.
Dim aLabel als nieuw systeem. Ramen. Formulieren. Etiket
'Voeg het label toe aan de collecties
'interne lijst.
Me. Lijst. Toevoegen (aLabel)
'Voeg het label toe aan de collectie Controls
'van het formulier waarnaar wordt verwezen door het veld HostForm.
HostForm. Bediening. Toevoegen (aLabel)
'Stel initiële eigenschappen in voor het Label-object.
een label. Top = tellen * 25
een label. Breedte = 50
een label. Links = 140
een label. Tag = ik. Tel
een label. Text = "Label" & ik. Tel. ToString
Retourneer aLabel
Einde functie
Public Sub New (_
ByVal host als systeem. Ramen. Formulieren. Het formulier)
HostForm = host
Me. AddNewLabel ()
Einde Sub
Standaard openbare ReadOnly-eigenschap _
Item (ByVal Index As Integer) As _
Systeem. Ramen. Formulieren. Etiket
Krijgen
Return CType (Me. List. Item (Index), _
Systeem. Ramen. Formulieren. Etiket)
Einde ophalen
Eigendom beëindigen
Openbare sub verwijderen ()
'Controleer of er een label is dat moet worden verwijderd.
Als ik. Tel> 0 Dan
'Verwijder het laatste label dat aan de array is toegevoegd
'van de host-formulier controleert collectie.
'Let op het gebruik van de standaard eigenschap in
'toegang tot de array.
HostForm. Bediening. Verwijderen (Me (Me. Count - 1))
Me. Lijst. RemoveAt (Me. Count - 1)
Stop als
Einde Sub
Einde klasse

Om te illustreren hoe deze klassecode zou worden gebruikt, kunt u een formulier maken dat deze aanroept. U moet de onderstaande code gebruiken in het formulier:

Openbare klassenformulier 1. Erft systeem. Ramen. Formulieren. Het formulier. #Region "Door Windows Form Designer gegenereerde code" 'U moet ook de verklaring toevoegen:' MyControlArray = New LabelArray (Me) 'na de InitializeComponent () aanroep van de. 'verborgen regiocode. 'Verklaar een nieuw ButtonArray-object. Dim MyControlArray als LabelArray. Private Sub btnLabelAdd_Click (_. ByVal-afzender als systeem. Voorwerp, _. ByVal e als systeem. EventArgs) _. Behandelt btnLabelAdd. Klik. 'Roep de AddNewLabel-methode aan. 'van MyControlArray. MyControlArray. AddNewLabel () 'Wijzig de eigenschap BackColor. 'van de knop 0. MyControlArray (0) .BackColor = _. Systeem. Tekening. Kleur. Rood. Einde Sub. Private Sub btnLabelRemove_Click (_. ByVal-afzender als systeem. Voorwerp, _. ByVal e als systeem. EventArgs) _. Behandelt btnLabelRemove. Klik. 'Roep de verwijdermethode van MyControlArray aan. MyControlArray. Verwijderen() Einde Sub. Einde klasse

Ten eerste werkt dit niet eens tijdens Design Time zoals we het vroeger deden in VB 6! En ten tweede, ze bevinden zich niet in een array, ze bevinden zich in een VB.NET-collectie - iets heel anders dan een array.

De reden dat VB.NET de "control array" van VB 6 niet ondersteunt, is dat er niet zoiets bestaat als een "control" "array" (let op de wijziging tussen aanhalingstekens). VB 6 creëert een verzameling achter de schermen en laat deze verschijnen als een array voor de ontwikkelaar. Maar het is geen array en je hebt er weinig controle over, afgezien van de functies die via de IDE worden geboden.

VB.NET daarentegen noemt het wat het is: een verzameling objecten. En ze geven de sleutels van het koninkrijk aan de ontwikkelaar door alles in het openbaar te maken.

Als voorbeeld van het soort voordelen dat dit de ontwikkelaar geeft, moesten in VB 6 de bedieningselementen van hetzelfde type zijn en dezelfde naam hebben. Aangezien dit slechts objecten in VB.NET zijn, kunt u ze van verschillende typen maken en ze verschillende namen geven en ze toch beheren in dezelfde verzameling objecten.

In dit voorbeeld behandelt dezelfde Click-gebeurtenis twee knoppen en een selectievakje en wordt weergegeven op welke is geklikt. Doe dat in één regel code met VB 6!

Private Sub MixedControls_Click (_
ByVal-afzender als systeem. Voorwerp, _
ByVal e als systeem. EventArgs) _
Knop Handles 1. klik, _
Button2.Click, _
CheckBox1.Klik
'De onderstaande verklaring moet één lange verklaring zijn!
'Het staat hier op vier regels om het smal te houden
'genoeg om op een webpagina te passen
Label2.Text =
Microsoft. VisualBasic. Juist (afzender. GetType. ToString,
Len (afzender. GetType. ToString) -
(InStr (afzender. GetType. ToString, "Forms") + 5))
Einde Sub

De berekening van de substring is nogal complex, maar het is niet echt waar we het hier over hebben. Je kunt alles doen in het Click-evenement. U kunt bijvoorbeeld het type van het besturingselement in een If-instructie gebruiken om verschillende dingen te doen voor verschillende besturingselementen.

Frank's Computing Studies Group Feedback op arrays

Frank's Study Group gaf een voorbeeld met een formulier met 4 labels en 2 knoppen. Knop 1 wist de labels en knop 2 vult ze. Het is een goed idee om Franks oorspronkelijke vraag opnieuw te lezen en op te merken dat het voorbeeld dat hij gebruikte een lus was die werd gebruikt om de eigenschap Caption van een reeks labelcomponenten te wissen. Hier is het VB.NET-equivalent van die VB 6-code. Deze code doet wat Frank oorspronkelijk had gevraagd!

Openbare klassenformulier 1. Erft systeem. Ramen. Formulieren. Het formulier. #Region "Door Windows Form Designer gegenereerde code" Dim LabelArray (4) als label. 'verklaren een reeks labels. Private Sub Form1_Load (_. ByVal-afzender als systeem. Voorwerp, _. ByVal e als systeem. EventArgs) _. Behandelt MyBase. Laden. SetControlArray () Einde Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. Einde Sub. Private Sub Button 1_Click (_. ByVal-afzender als systeem. Voorwerp, _. ByVal e als systeem. EventArgs) _. Knop Handles 1. klik. 'Knop 1 Clear Array. Dim a als geheel getal. Voor a = 1 tot 4. LabelArray (a) .Text = "" De volgende. Einde Sub. Private Sub Button2_Click (_. ByVal-afzender als systeem. Voorwerp, _. ByVal e als systeem. EventArgs) _. Knop Handles 2. Klik. 'Knop 2 Array vullen. Dim a als geheel getal. Voor a = 1 tot 4. LabelArray (a) .Text = _. "Control Array" & CStr (a) De volgende. Einde Sub. Einde klasse

Als je met deze code experimenteert, zul je ontdekken dat je naast het instellen van eigenschappen van de Labels ook methoden kunt aanroepen. Dus waarom heb ik (en Microsoft) alle moeite gedaan om de "lelijke" code in deel I van het artikel te bouwen?

Ik ben het er niet mee eens dat het echt een "Control Array" is in de klassieke VB-zin. De VB 6 Control Array is een ondersteund onderdeel van de VB 6-syntaxis, niet alleen een techniek. Misschien is de manier om dit voorbeeld te beschrijven misschien dat het een reeks besturingselementen is en geen besturingsmatrix.

In deel I klaagde ik dat het Microsoft-voorbeeld ALLEEN werkte tijdens runtime en niet tijdens ontwerptijd. U kunt besturingselementen dynamisch vanuit een formulier toevoegen en verwijderen, maar het geheel moet in code worden geïmplementeerd. Je kunt besturingselementen niet slepen en neerzetten om ze te maken zoals je kunt in VB 6. Dit voorbeeld werkt voornamelijk tijdens de ontwerptijd en niet tijdens de uitvoering. U kunt tijdens de uitvoering geen besturingselementen dynamisch toevoegen en verwijderen. In zekere zin is dit het tegenovergestelde van het voorbeeld van deel I.

Het klassieke voorbeeld van de VB 6-besturingsarray is dezelfde als die is geïmplementeerd in de VB .NET-code. Hier in VB 6-code (dit is afkomstig van Mezick & Hillier, Visual Basic 6-certificeringsexamengids, p 206 - enigszins gewijzigd, aangezien het voorbeeld in het boek resulteert in controles die niet zichtbaar zijn):

Dim MyTextBox als VB.TextBox. Statisch intNumber als geheel getal. intNumber = intNumber + 1. Stel MyTextBox = _ in. Me. Bediening. Voeg toe ("VB.TextBox", _. "Tekst" & intNumber) MyTextBox. Tekst = MyTextBox. Naam. MyTextBox. Zichtbaar = waar. MyTextBox. Links = _. (intNumber - 1) * 1200

Maar zoals Microsoft (en ik) het ermee eens zijn, zijn VB 6-besturingsarrays niet mogelijk in VB.NET. U kunt dus het beste de functionaliteit dupliceren. Mijn artikel heeft de functionaliteit van het Mezick & Hillier-voorbeeld gedupliceerd. De studiegroepcode dupliceert de functionaliteit van het kunnen instellen van eigenschappen en oproepmethoden.

Het komt er dus op neer dat het echt afhangt van wat je wilt doen. VB.NET heeft niet alles in de taal verpakt - maar - maar uiteindelijk is het veel flexibeler.

John Fannons Take on Control Arrays

John schreef: Ik had controlearrays nodig omdat ik tijdens runtime een eenvoudige tabel met getallen op een formulier wilde zetten. Ik wilde niet de misselijkheid om ze allemaal afzonderlijk te plaatsen en ik wilde VB.NET gebruiken. Microsoft biedt een zeer gedetailleerde oplossing voor een eenvoudig probleem, maar het is een zeer grote voorhamer om een ​​heel kleine noot te kraken. Na wat experimenteren kwam ik uiteindelijk op een oplossing. Hier is hoe ik het heb gedaan.

Het Over Visual Basic-voorbeeld hierboven laat zien hoe u een TextBox op een formulier kunt maken door een instantie te maken van het object, eigenschappen instellen en toevoegen aan de collectie Controls die deel uitmaakt van het formulier voorwerp.

Dim txtDataShow As New TextBox
txtDataShow. Hoogte = 19
txtDataShow. Breedte = 80
txtDataShow. Locatie = nieuw punt (X, Y)
Me. Bediening. Toevoegen (txtDataShow)
Hoewel de Microsoft-oplossing een klasse creëert, redeneerde ik dat het mogelijk zou zijn om dit allemaal in een subroutine te verpakken. Elke keer dat u deze subroutine aanroept, maakt u een nieuw exemplaar van het tekstvak op het formulier. Hier is de volledige code:

Openbare klassenformulier 1
Erft systeem. Ramen. Formulieren. Het formulier

#Region "Door Windows Form Designer gegenereerde code"

Private Sub BtnStart_Click (_
ByVal-afzender als systeem. Voorwerp, _
ByVal e als systeem. EventArgs) _
Handgrepen btnStart. Klik

Dim I als geheel getal
Dim sData als tekenreeks
Voor I = 1 tot 5
sData = CStr (I)
Bel AddDataShow (sData, I)
De volgende
Einde 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 geheel getal
UserLft = 20
UserTop = 20
txtDataShow. Hoogte = 19
txtDataShow. Breedte = 25
txtDataShow. TextAlign = _
Horizontale uitlijning. Centrum
txtDataShow. BorderStyle = _
BorderStyle. FixedSingle
txtDataShow. Tekst = tekst
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Hoogte
txtDataShow. Locatie = nieuw punt (X, Y)
Me. Bediening. Toevoegen (txtDataShow)
Einde Sub
Einde klasse
Heel goed punt, John. Dit is zeker een stuk eenvoudiger dan de Microsoft-code... dus ik vraag me af waarom ze erop stonden het zo te doen?

Laten we om ons onderzoek te beginnen een van de eigenschapsopdrachten in de code wijzigen. Laten we veranderen

txtDataShow. Hoogte = 19
naar

txtDataShow. Hoogte = 100
om er zeker van te zijn dat er een merkbaar verschil is.

Wanneer we de code opnieuw uitvoeren, krijgen we... Whaaaat??? ... hetzelfde. Helemaal geen verandering. U kunt de waarde zelfs weergeven met een instructie als MsgBox (txtDataShow. Hoogte) en u krijgt nog steeds 20 als de waarde van het onroerend goed, ongeacht wat u eraan toewijst. Waarom gebeurt dat?

Het antwoord is dat we niet onze eigen klasse afleiden om de objecten te maken, we voegen alleen dingen toe aan een andere klasse, dus we moeten de regels van de andere klasse volgen. En in die regels staat dat u de eigenschap Height niet kunt wijzigen. (Wellllll... jij kan. Als u de eigenschap Multiline wijzigt in True, kunt u de hoogte wijzigen.)

Waarom VB.NET doorgaat en de code uitvoert zonder zelfs maar te jammeren dat er misschien iets mis is, terwijl het in feite uw verklaring volledig negeert, is een heel ander probleem. Ik zou echter in ieder geval een waarschuwing in de compilatie kunnen suggereren. (Hint! Tip! Tip! Luistert Microsoft?)

Het voorbeeld uit deel I erft van een andere klasse en dit maakt de eigenschappen beschikbaar voor de code in de overnemende klasse. Als u de eigenschap Height in dit voorbeeld wijzigt in 100, krijgt u de verwachte resultaten. (Nog een keer... één disclaimer: wanneer een nieuw exemplaar van een groot labelonderdeel wordt gemaakt, wordt het oude afgedekt. Om de nieuwe Label-componenten daadwerkelijk te zien, moet je de methodeaanroep aLabel toevoegen. Naar voren brengen().)

Dit eenvoudige voorbeeld laat zien dat, hoewel we eenvoudig objecten aan een andere klasse kunnen toevoegen (en soms is dit het juiste om te doen), het programmeren van controle over de objecten vereist dat we ze in een klasse afleiden en de meest georganiseerde manier (durf ik te zeggen "de .NET-manier" ??) is om eigenschappen en methoden te creëren in de nieuwe afgeleide klasse om te veranderen dingen. John was aanvankelijk niet overtuigd. Hij zei dat zijn nieuwe aanpak bij zijn doel past, ook al zijn er beperkingen aan het niet "COO" zijn (Correctly Object Oriented). Meer recentelijk schreef John echter:

"... na het schrijven van een set van 5 tekstvakken tijdens runtime, wilde ik de gegevens bijwerken in een volgend deel van het programma - maar er veranderde niets - de originele gegevens waren er nog steeds.

Ik ontdekte dat ik het probleem kon omzeilen door code te schrijven om de oude dozen te verwijderen en ze weer terug te plaatsen met nieuwe gegevens. Een betere manier om dit te doen is door Mij te gebruiken. Vernieuwen. Maar dit probleem heeft mijn aandacht getrokken voor de noodzaak om een ​​methode te bieden om de tekstvakken af ​​te trekken en toe te voegen. "

John's code gebruikte een globale variabele om bij te houden hoeveel controles er aan het formulier waren toegevoegd, dus een methode ...

Private Sub Form1_Load (_
ByVal-afzender als systeem. Voorwerp, _
ByVal e als systeem. EventArgs) _
Behandelt MyBase. Laden
CntlCnt0 = Ik. Bediening. Tel
Einde Sub

Dan kon de "laatste" controle worden verwijderd ...

N = ik. Bediening. Tellen - 1
Me. Bediening. RemoveAt (N)
John merkte op: "misschien is dit een beetje onhandig."

Het is de manier waarop Microsoft objecten in COM EN bijhoudt in hun "lelijke" voorbeeldcode hierboven.

Ik ben nu teruggekeerd naar het probleem van het dynamisch maken van besturingselementen op een formulier tijdens runtime en ik heb opnieuw gekeken naar de artikelen 'What Happened to Control Arrays'.

Ik heb de klassen gemaakt en kan nu de bedieningselementen op het formulier plaatsen zoals ik dat wil.

John demonstreerde hoe hij de plaatsing van bedieningselementen in een groepsvak kan regelen met behulp van de nieuwe klassen die hij is gaan gebruiken. Misschien had Microsoft het toch goed in hun "lelijke" oplossing!

instagram story viewer