VB.NET: Hvad skete der med kontrolpaneler

Udeladelse af kontrolarrays fra VB.NET er en udfordring for dem, der underviser om arrays.

  • Det er ikke længere muligt blot at kopiere en kontrol, f.eks. En tekstboks, og derefter indsætte den (en eller flere gange) for at oprette en kontrolgruppe.
  • VB.NET-koden til at oprette en struktur, der ligner en kontrolgruppe, har været i alle de bøger på VB.NET, som jeg har købt og online, meget længere og meget mere kompleks. Det mangler enkelheden ved at kode en kontrolgruppe, der findes i VB6.

Hvis du refererer til VB6-kompatibilitetsbiblioteket, er der objekter derinde, der fungerer stort set som kontrolarrays. For at se, hvad jeg mener, skal du blot bruge VB.NET-opgraderingsguiden med et program, der indeholder et kontrolarray. Koden er grim igen, men den fungerer. Den dårlige nyhed er, at Microsoft ikke garanterer, at kompatibilitetskomponenterne fortsat vil blive understøttet, og du skal ikke bruge dem.

VB.NET-koden til at oprette og bruge "kontrolpaneler" er meget længere og meget mere kompleks.

instagram viewer

Ifølge Microsoft kræver oprettelse af en "simpel komponent, der duplikerer kontrol array-funktionalitet" for at gøre noget endda hvad du kan gøre i VB 6.

Du har brug for både en ny klasse og en hostingformular for at illustrere dette. Klassen opretter og ødelægger faktisk nye labels. Den komplette klassekode er som følger:

Public Class LabelArray
Arv System. Samlinger. CollectionBase
Privat readOnly HostForm As _
System. Windows. Formularer. Form
Offentlig funktion AddNewLabel () _
Som system. Windows. Formularer. Etiket
'Opret en ny forekomst af klassen Label.
Dim aLabel som nyt system. Windows. Formularer. Etiket
'Føj etiketten til samlingen
'intern liste.
Mig. Liste. Tilføj (aLabel)
'Føj etiketten til samlingen Controls
'af formularen, der henvises til i feltet HostForm.
HostForm. Controls. Tilføj (aLabel)
'Indstil intiale egenskaber for Label-objektet.
aLabel. Top = Count * 25
aLabel. Bredde = 50
aLabel. Venstre = 140
aLabel. Tag = mig. Tælle
aLabel. Tekst = "Label" & mig. Tælle. toString
Returner aLabel
Slut Funktion
Public Sub New (_
ByVal vært som system. Windows. Formularer. Form)
HostForm = vært
Mig. AddNewLabel ()
Afslut under
Standard offentlig readOnly ejendom _
Element (ByVal-indeks som heltal) Som _
System. Windows. Formularer. Etiket

Returner CType (Me. List. Vare (indeks), _
System. Windows. Formularer. Etiket)
Slut Get
Slut ejendom
Public Sub Fjern ()
'Kontroller, at der er et mærke, der skal fjernes.
Hvis mig. Tæl> 0 Derefter
'Fjern det sidste etiket, der blev tilføjet til matrixen
'fra værtsformularen kontrollerer samlingen.
'Bemærk brugen af ​​standardejendommen i
'adgang til matrixen.
HostForm. Controls. Fjern (mig (mig. Tælling - 1))
Mig. Liste. FjernAt (Me. Count - 1)
Afslut Hvis
Afslut under
Slutteklasse

For at illustrere, hvordan denne klassekode ville blive brugt, kan du oprette en formular, der kalder den. Du bliver nødt til at bruge koden vist nedenfor i formularen:

Offentlig klasseskema1. Arv System. Windows. Formularer. Form. #Region "Windows Form Designer genereret kode" 'Du skal også tilføje udsagnet:' MyControlArray = New LabelArray (Me) efter opkaldet til InitializeComponent (). 'skjult regionskode. 'Erklær et nyt ButtonArray-objekt. Dim MyControlArray som LabelArray. Privat sub btnLabelAdd_Click (_. ByVal afsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer btnLabelAdd. Klik. 'Ring til metoden AddNewLabel. 'af MyControlArray. MyControlArray. AddNewLabel () 'Skift egenskaben BackColor. 'af knappen 0. MyControlArray (0) .BackColor = _. System. Tegning. Farve. Rød. Afslut under. Privat sub btnLabelRemove_Click (_. ByVal afsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer btnLabelFjern. Klik. 'Ring til metoden Fjern på MyControlArray. MyControlArray. Fjerne() Afslut under. Slutteklasse

For det første gør dette ikke engang arbejdet på Design Time, som vi plejede at gøre det i VB 6! Og for det andet er de ikke i en matrix, de er i en VB.NET-samling - en meget anden ting end en matrix.

Årsagen til, at VB.NET ikke understøtter VB 6 "kontrolarray", er, at der ikke findes noget som et "kontrol" "array" (bemærk ændringen af ​​anførselstegn). VB 6 opretter en samling bag kulisserne og får den til at vises som en matrix for udvikleren. Men det er ikke et array, og du har lidt kontrol over det ud over de funktioner, der leveres gennem IDE.

På den anden side kalder VB.NET det, hvad det er: en samling objekter. Og de overleverer nøglerne til kongeriget til udvikleren ved at skabe det hele lige ud i det fri.

Som et eksempel på den slags fordele, dette giver udvikleren, i VB 6 måtte kontrollerne være af samme type, og de måtte have samme navn. Da dette kun er objekter i VB.NET, kan du lave dem forskellige typer og give dem forskellige navne og stadig administrere dem i den samme samling af objekter.

I dette eksempel håndterer den samme Click-begivenhed to knapper og et afkrydsningsfelt og viser, hvilken der blev klikket på. Gør det i en kodelinje med VB 6!

Privat sub MixedControls_Click (_
ByVal afsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndtag-knap1.Klik, _
Knap2.Klik, _
CheckBox1.Click
'Udsagnet nedenfor skal være en lang erklæring!
”Det er på fire linjer her for at holde det smalt
'nok til at passe på en webside
Label2.Text =
Microsoft. VisualBasic. Højre (afsender. GetType. toString,
Len (afsender. GetType. ToString) -
(InStr (afsender. GetType. ToString, "Formularer") + 5))
Afslut under

Substringsberegningen er slags kompleks, men det er ikke rigtig det, vi taler om her. Du kan gøre hvad som helst i Click-begivenheden. Du kan f.eks. Bruge kontroltypen i en If-sætning til at gøre forskellige ting til forskellige kontroller.

Frank's Group Computing Studies Group Feedback om Arrays

Frank's Study Group gav et eksempel med en formular, der har 4 etiketter og 2 knapper. Knap 1 rydder etiketterne, og knap 2 udfylder dem. Det er en god ide at læse Franks oprindelige spørgsmål igen og bemærke, at eksemplet, han brugte, var en løkke, der bruges til at rydde billedtekstegenskab for en række Label-komponenter. Her er VB.NET-ækvivalenten til den VB 6-kode. Denne kode gør det, som Frank oprindeligt bad om!

Offentlig klasseskema1. Arv System. Windows. Formularer. Form. #Region "Windows Form Designer genereret kode" Dim LabelArray (4) Som etiket. 'erklærer en række etiketter. Privat underformular1_Load (_. ByVal afsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer MyBase. Belastning. SetControlArray () Afslut under. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. Afslut under. Privat underknap1_Klik (_. ByVal afsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndtag-knap1.Klik. 'Knap 1 Ryd Array. Dim et som heltal. For a = 1 til 4. LabelArray (a) .Tekst = "" Næste. Afslut under. Privat underknap2_Klik (_. ByVal afsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndtagsknap 2. Klik. 'Knap 2 Fyld Array. Dim et som heltal. For a = 1 til 4. LabelArray (a). Tekst = _. "Control Array" & CStr (a) Næste. Afslut under. Slutteklasse

Hvis du eksperimenterer med denne kode, vil du opdage, at ud over at indstille egenskaber for etiketterne, kan du også kalde metoder. Så hvorfor gik jeg (og Microsoft) til alle problemer med at opbygge den "grimme" kode i del I af artiklen?

Jeg må være uenig i, at det virkelig er en "Control Array" i den klassiske VB-forstand. VB 6 Control Array er en understøttet del af VB 6-syntaks, ikke kun en teknik. Faktisk er måden måden at beskrive dette eksempel på, at det er en række kontroller, ikke en kontrolgruppe.

I del I klagede jeg over, at Microsoft-eksemplet KUN fungerede på kørselstidspunkt og ikke designtid. Du kan tilføje og slette kontroller fra en form dynamisk, men det hele skal implementeres i kode. Du kan ikke trække og slippe kontrollerne for at oprette dem, som du kan i VB 6. Dette eksempel fungerer hovedsageligt på designtidspunkt og ikke på kørselstidspunkt. Du kan ikke tilføje og slette kontroller dynamisk på kørselstidspunktet. På en måde er det den fuldstændige modsætning til eksempel I-eksemplet.

Det klassiske VB 6-kontrolarrayeksempel er det samme, der implementeres i VB .NET-koden. Her i VB 6-kode (dette er hentet fra Mezick & Hillier, Visual Basic 6-certificeringseksamen Vejledning, s 206 - lidt ændret, da eksemplet i bogen resulterer i kontroller, der ikke kan ses):

Dim MyTextBox som VB.TextBox. Statisk intNummer som heltal. intNumber = intNumber + 1. Indstil MyTextBox = _. Mig. Controls. Tilføj ("VB.TextBox", _. "Tekst" & intNummer) Mintekstboks. Tekst = MyTextBox. Navn. Mintekstboks. Synlig = sandt. Mintekstboks. Venstre = _. (intNummer - 1) * 1200

Men som Microsoft (og jeg) er enige, er VB 6-kontrolpaneler ikke mulige i VB.NET. Så det bedste du kan gøre er at kopiere funktionaliteten. Min artikel duplikerede funktionaliteten, der findes i Mezick & Hillier-eksemplet. Studiegruppekoden duplikerer funktionaliteten ved at være i stand til at indstille egenskaber og opkaldsmetoder.

Så bunden er, at det virkelig afhænger af, hvad du vil gøre. VB.NET har ikke det hele pakket ind som en del af sproget - alligevel - men i sidste ende er det langt mere fleksibelt.

John Fannons Take on Control Arrays

John skrev: Jeg havde brug for kontrolpaneler, fordi jeg ville sætte en enkel tabel med numre på en formular på kørselstidspunktet. Jeg ville ikke have kvalmen ved at placere dem alle individuelt, og jeg ville bruge VB.NET. Microsoft tilbyder en meget detaljeret løsning på et simpelt problem, men det er en meget stor slegge at knække en meget lille nød. Efter nogle eksperimenter ramte jeg efterhånden en løsning. Sådan gjorde jeg det.

Eksemplet About Visual Basic ovenfor viser, hvordan du kan oprette en TextBox på en formular ved at oprette en instans af objektet, indstille egenskaber og tilføje det til samlingen Kontroller, der er en del af formularen objekt.

Dim txtDataVis som ny tekstboks
txtDataShow. Højde = 19
txtDataShow. Bredde = 80
txtDataShow. Placering = nyt punkt (X, Y)
Mig. Controls. Tilføj (txtDataShow)
Selvom Microsoft-løsningen opretter en klasse, begrundede jeg, at det ville være muligt at pakke alt dette i en subroutine i stedet. Hver gang du ringer til denne subroutine, opretter du en ny forekomst af tekstboksen på formularen. Her er den komplette kode:

Offentlig klasseskema1
Arv System. Windows. Formularer. Form

#Region "Windows Form Designer genereret kode"

Privat sub BtnStart_Click (_
ByVal afsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndterer btnStart. Klik

Dim I som heltal
Dim sData som streng
For I = 1 til 5
sData = CStr (I)
Ring til AddDataShow (sData, I)
Næste
Afslut under
Sub AddDataShow (_
ByVal sText As String, _
ByVal I som heltal)

Dim txtDataVis som ny tekstboks
Dim UserLft, UserTop som heltal
Dim X, Y Som heltal
UserLft = 20
UserTop = 20
txtDataShow. Højde = 19
txtDataShow. Bredde = 25
txtDataShow. TextAlign = _
HorizontalAlignment. Centrum
txtDataShow. BorderStyle = _
Kantstil. FixedSingle
txtDataShow. Tekst = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Højde
txtDataShow. Placering = nyt punkt (X, Y)
Mig. Controls. Tilføj (txtDataShow)
Afslut under
Slutteklasse
Meget godt punkt, John. Dette er bestemt meget mere simpelt end Microsoft-koden... så jeg spekulerer på, hvorfor de insisterede på at gøre det på den måde?

For at begynde vores undersøgelse, lad os prøve at ændre en af ​​egenskabsopgaverne i koden. Lad os ændre os

txtDataShow. Højde = 19
til

txtDataShow. Højde = 100
bare for at sikre, at der er en mærkbar forskel.

Når vi kører koden igen, får vi... Whaaaat??? ... det samme. Ingen ændring overhovedet. Faktisk kan du vise værdien med en sætning som MsgBox (txtDataShow. Højde), og du får stadig 20 som værdien af ​​ejendommen, uanset hvad du tildeler den. Hvorfor sker det?

Svaret er, at vi ikke udleder vores egen klasse for at oprette objekter, vi tilføjer bare ting til en anden klasse, så vi er nødt til at følge reglerne for den anden klasse. Og disse regler angiver, at du ikke kan ændre Højdeegenskapen. (Wellllll... du kan. Hvis du ændrer egenskaben Multiline til True, kan du ændre højden.)

Hvorfor VB.NET går foran og udfører koden uden engang at klynke over, at der muligvis er noget galt, når det faktisk ignorerer din erklæring er en hel 'nother gripe. Jeg foreslår dog i det mindste en advarsel i kompilationen. (Antydning! Antydning! Antydning! Lytter Microsoft?)

Eksemplet fra del I arver fra en anden klasse, og dette gør egenskaberne tilgængelige for koden i arveklassen. Ændring af egenskaben Højde til 100 i dette eksempel giver os de forventede resultater. (Igen... en ansvarsfraskrivelse: Når der oprettes en ny forekomst af en stor etiketkomponent, dækker den den gamle. For faktisk at se de nye Label-komponenter, skal du tilføje metodekaldet aLabel. Tage den op foran().)

Dette enkle eksempel viser, at selvom vi KAN blot tilføje objekter til en anden klasse (og sommetider er det den rigtige ting at gøre), programmerer du kontrol over objekterne kræver, at vi udleder dem i en klasse og den mest organiserede måde (tør jeg sige, ". NET-måde" ??) er at oprette egenskaber og metoder i den nye afledte klasse til at ændre ting. John forblev uoverbevist i starten. Han sagde, at hans nye tilgang passer til hans formål, selvom der er begrænsninger fra ikke at være "COO" (Korrekt objektorienteret). Mere for nylig skrev John imidlertid,

"... efter at have skrevet et sæt af 5 tekstbokse under kørsel, ønskede jeg at opdatere dataene i en efterfølgende del af programmet - men intet ændrede sig - de originale data var stadig der.

Jeg fandt, at jeg kunne komme rundt om problemet ved at skrive kode for at tage de gamle kasser af og sætte dem tilbage igen med nye data. En bedre måde at gøre det på ville være at bruge Mig. Opdater. Men dette problem har trukket min opmærksomhed på behovet for at levere en metode til at trække tekstbokse samt tilføje dem. "

Johns kode brugte en global variabel til at holde styr på, hvor mange kontroller der var tilføjet til formularen, så en metode ...

Privat underformular1_Load (_
ByVal afsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndterer MyBase. belastning
CntlCnt0 = Mig. Controls. Tælle
Afslut under

Derefter kunne den "sidste" kontrol fjernes ...

N = Mig. Controls. Tælle - 1
Mig. Controls. FjernAt (N)
John bemærkede, at "måske er dette en smule klodset."

Det er den måde, Microsoft holder styr på objekter i KOM OG I deres "grimme" eksempelkode ovenfor.

Jeg er nu vendt tilbage til problemet med dynamisk oprettelse af kontroller på en formular på kørselstidspunktet, og jeg har igen set på artiklene "Hvad der skete med kontrolarrangementer".

Jeg har oprettet klasserne og kan nu placere kontrollerne på formen på den måde, jeg vil have dem til at være.

John demonstrerede, hvordan man kontrollerer placeringen af ​​kontroller i en gruppekasse ved hjælp af de nye klasser, han er begyndt at bruge. Måske Microsoft havde det rigtigt i deres "grimme" løsning trods alt!