Utelatelse av kontrollmatriser fra VB.NET er en utfordring for de som lærer om matriser.
- Det er ikke lenger mulig å bare kopiere en kontroll, for eksempel en tekstboks, og deretter lime den inn (en eller flere ganger) for å opprette en kontrollgruppe.
- VB.NET-koden for å lage en struktur som ligner på en kontrollgruppe har vært, i alle bøkene på VB.NET som jeg har kjøpt og online, mye lengre og mye mer kompleks. Det mangler enkelheten i å kode en kontrollgruppe som finnes i VB6.
Hvis du refererer til VB6-kompatibilitetsbiblioteket, er det objekter der som fungerer ganske mye som kontrollmatriser. For å se hva jeg mener, bare bruk VB.NET oppgraderingsveiviseren med et program som inneholder en kontrollmatrise. Koden er stygg igjen, men den fungerer. Den dårlige nyheten er at Microsoft ikke vil garantere at kompatibilitetskomponentene fortsatt vil bli støttet, og at du ikke skal bruke dem.
VB.NET-koden for å lage og bruke "kontrollmatriser" er mye lenger og mye mer kompleks.
I følge Microsoft krever å lage noe til og med nær det du kan gjøre i VB 6, opprettelsen av en "enkel komponent som dupliserer kontrollfunksjonalitet."
Du trenger både en ny klasse og et vertskjema for å illustrere dette. Klassen skaper og ødelegger faktisk nye etiketter. Den komplette klassekoden er som følger:
Public Class LabelArray
Arv System. Samlinger. CollectionBase
Privat ReadOnly HostForm As _
System. Windows. Former. Form
Offentlig funksjon AddNewLabel () _
Som system. Windows. Former. Merkelapp
'Lag en ny forekomst av klassen Label.
Dim aLabel som nytt system. Windows. Former. Merkelapp
'Legg etiketten til samlingen
'intern liste.
Meg. Liste. Legg til (aLabel)
Legg til etiketten i kontrollen-samlingen
'av skjemaet referert av HostForm-feltet.
HostForm. Kontroller. Legg til (aLabel)
'Angi intielle egenskaper for Label-objektet.
en merkelapp. Topp = Count * 25
en merkelapp. Bredde = 50
en merkelapp. Venstre = 140
en merkelapp. Tag = Meg. Telle
en merkelapp. Tekst = "Etikett" og meg. Telle. toString
Returner etikett
Sluttfunksjon
Public Sub New (_
ByVal vert As System. Windows. Former. Form)
HostForm = vert
Meg. AddNewLabel ()
Slutt sub
Standard offentlig readOnly eiendom _
Element (ByVal-indeks som heltall) Som _
System. Windows. Former. Merkelapp
Få
Returner CType (Me. List. Vare (indeks), _
System. Windows. Former. Merkelapp)
Slutt Get
Slutteiendom
Offentlig underfjerning ()
'Kontroller at det er en etikett å fjerne.
Hvis jeg. Telle> 0 Da
Fjern den siste etiketten som ble lagt til i matrisen
'fra vertskjemaet styrer samlingen.
'Merk bruken av standardegenskapen i
tilgang til matrisen.
HostForm. Kontroller. Fjern (meg (meg. Teller - 1))
Meg. Liste. RemoveAt (Me. Count - 1)
Slutt om
Slutt sub
Sluttklasse
For å illustrere hvordan denne klassekoden ville bli brukt, kan du lage et skjema som kaller det. Du må bruke koden vist nedenfor i skjemaet:
Offentlig klasseskjema1. Arv System. Windows. Former. Form. #Region "Windows Form Designer generert kode" 'Du må også legge til uttalelsen:' MyControlArray = New LabelArray (Me) 'etter at InitializeComponent () ringer inn. skjult regionskode. 'Forkynn et nytt ButtonArray-objekt. Dim MyControlArray As LabelArray. Privat sub btnLabelAdd_Click (_. ByVal avsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer btnLabelAdd. Klikk. 'Ring AddNewLabel-metoden. av MyControlArray. MyControlArray. AddNewLabel () 'Endre BackColor-egenskapen. av knappen 0. MyControlArray (0). BackColor = _. System. Tegning. Farge. Rød. Slutt sub. Privat sub btnLabelRemove_Click (_. ByVal avsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer btnLabelFjerne. Klikk. "Ring Fjern metoden for MyControlArray. MyControlArray. Fjerne() Slutt sub. Sluttklasse
For det første gjør dette ikke en gang jobben på Design Time som vi pleide å gjøre det i VB 6! Og for det andre: De er ikke i en matrise, de er i en VB.NET-samling - en mye annen ting enn en matrise.
Årsaken til at VB.NET ikke støtter VB 6 "kontrollarray" er at det ikke er noe som heter et "kontroll" "array" (merk endringen av anførselstegn). VB 6 lager en samling bak kulissene og får den til å fremstå som en matrise for utvikleren. Men det er ikke et utvalg, og du har liten kontroll over det utover funksjonene som tilbys gjennom IDE.
VB.NET derimot kaller det hva det er: en samling av objekter. Og de overlater nøklene til riket til utvikleren ved å lage hele saken rett ut i det fri.
Som et eksempel på den typen fordeler dette gir utvikleren, i VB 6 måtte kontrollene være av samme type, og de måtte ha samme navn. Siden dette bare er objekter i VB.NET, kan du lage dem til forskjellige typer og gi dem forskjellige navn og fremdeles administrere dem i samme samling av objekter.
I dette eksemplet håndterer den samme Click-hendelsen to knapper og en avmerkingsboks og viser hvilken som ble klikket. Gjør det på en kodelinje med VB 6!
Privat sub MixedControls_Click (_
ByVal avsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndtak-knapp1.Klikk, _
Knapp2.Klikk, _
CheckBox1.Click
Uttalelsen nedenfor må være en lang uttalelse!
'Det er på fire linjer her for å holde det smalt
nok til å passe på en webside
Label2.Text =
Microsoft. Visual. Til høyre (avsender. GetType. toString,
Len (avsender. GetType. ToString) -
(InStr (avsender. GetType. ToString, "Forms") + 5))
Slutt sub
Substringsberegningen er litt kompleks, men det er egentlig ikke det vi snakker om her. Du kan gjøre hva som helst i Click-arrangementet. Du kan for eksempel bruke kontrolltypen i et If-utsagn for å gjøre forskjellige ting for forskjellige kontroller.
Frank's Group Computing Studies Group Feedback on Arrays
Frank's Study Group ga et eksempel med et skjema som har 4 etiketter og 2 knapper. Knapp 1 tømmer etikettene, og knapp 2 fyller dem. Det er lurt å lese Franks originale spørsmål igjen og legge merke til at eksemplet han brukte var en sløyfe som brukes til å fjerne billedtekstegenskapen til en rekke etikettkomponenter. Her er VB.NET-ekvivalent med den VB 6-koden. Denne koden gjør det som Frank opprinnelig ba om!
Offentlig klasseskjema1. Arv System. Windows. Former. Form. #Region "Windows Form Designer generert kode" Dim LabelArray (4) Som etikett. erklære en rekke etiketter. Privat subform1_Load (_. ByVal avsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndterer MyBase. Laste. SetControlArray () Slutt sub. Sub SetControlArray () LabelArray (1) = Etikett1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. Slutt sub. Privat underknapp1_Klikk (_. ByVal avsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndtak-knapp1.Klikk. 'Knapp 1 Clear Array. Dim en som heltall. For a = 1 til 4. LabelArray (a) .Tekst = "" Neste. Slutt sub. Privat underknapp 2_Klikk (_. ByVal avsender som system. Objekt, _. ByVal e As System. EventArgs) _. Håndtak-knapp2.Klikk. 'Knapp 2 Fyll Array. Dim en som heltall. For a = 1 til 4. LabelArray (a). Tekst = _. "Control Array" og CStr (a) Neste. Slutt sub. Sluttklasse
Hvis du eksperimenterer med denne koden, vil du oppdage at du i tillegg til å angi egenskaper for etikettene, også kan ringe metoder. Så hvorfor gjorde jeg (og Microsoft) alle problemer med å bygge den "stygge" koden i del I av artikkelen?
Jeg må være uenig i at det egentlig er en "Control Array" i klassisk VB-forstand. VB 6 Control Array er en støttet del av VB 6-syntaks, ikke bare en teknikk. Faktisk er kanskje måten å beskrive dette eksemplet på at det er en rekke kontroller, ikke en kontrollgruppe.
I del I klaget jeg på at Microsoft-eksemplet KUN virket på kjøretid og ikke designtid. Du kan legge til og slette kontroller fra et skjema dynamisk, men det hele må implementeres i kode. Du kan ikke dra og slippe kontroller for å opprette dem som du kan i VB 6. Dette eksemplet fungerer hovedsakelig på designtid og ikke på kjøretid. Du kan ikke legge til og slette kontroller dynamisk på kjøretid. På en måte er det det motsatte av del I-eksemplet.
Det klassiske VB 6-kontrollarray-eksemplet er det samme som implementeres i VB .NET-koden. Her i VB 6-kode (dette er hentet fra Mezick & Hillier, Visual Basic 6 Certification Exam Guide, s 206 - litt modifisert, siden eksemplet i boken resulterer i kontroller som ikke kan sees):
Dim MyTextBox som VB.TextBox. Statisk nummer som heltall. intNumber = intNumber + 1. Angi MyTextBox = _. Meg. Kontroller. Legg til ("VB.TextBox", _. "Tekst" og intNummer) MyTextBox. Tekst = MyTextBox. Navn. MyTextBox. Synlig = sant. MyTextBox. Venstre = _. (intNummer - 1) * 1200
Men som Microsoft (og jeg) er enige, er VB 6-kontrollpaneler ikke mulig i VB.NET. Så det beste du kan gjøre er å duplisere funksjonaliteten. Artikkelen min dupliserte funksjonaliteten som finnes i Mezick & Hillier-eksemplet. Studiegruppekoden dupliserer funksjonaliteten til å kunne stille inn egenskaper og anropsmetoder.
Så poenget er at det virkelig kommer an på hva du vil gjøre. VB.NET har ikke alt innpakket som en del av språket - Likevel - men til syvende og sist er det langt mer fleksibelt.
John Fannons Take on Control Arrays
John skrev: Jeg trengte kontrollmatriser fordi jeg ønsket å legge en enkel tabell med tall på et skjema ved kjøretid. Jeg ønsket ikke kvalmen ved å plassere dem alle individuelt, og jeg ville bruke VB.NET. Microsoft tilbyr en veldig detaljert løsning på et enkelt problem, men det er en veldig stor slegge å sprekke en veldig liten mutter. Etter litt eksperimentering traff jeg til slutt en løsning. Slik gjorde jeg det.
Eksemplet About Visual Basic over viser hvordan du kan opprette en TextBox på et skjema ved å opprette en forekomst av objektet, innstille egenskaper og legge det til i kontrollsamlingen som er en del av skjemaet gjenstand.
Dim txtDataVis som ny tekstboks
txtDataShow. Høyde = 19
txtDataShow. Bredde = 80
txtDataShow. Plassering = nytt punkt (X, Y)
Meg. Kontroller. Legg til (txtDataShow)
Selv om Microsoft-løsningen oppretter en klasse, resonnerte jeg at det ville være mulig å pakke alt dette inn i en subroutine i stedet. Hver gang du ringer til denne subruten, oppretter du en ny forekomst av tekstboksen på skjemaet. Her er den komplette koden:
Offentlig klasseskjema1
Arv System. Windows. Former. Form
#Region "Windows Form Designer generert kode"
Privat sub BtnStart_Click (_
ByVal avsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndterer btnStart. Klikk
Dim I Som heltall
Dim sData Som streng
For jeg = 1 til 5
sData = CStr (I)
Ring AddDataShow (sData, I)
neste
Slutt sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I Som heltall)
Dim txtDataVis som ny tekstboks
Dim UserLft, UserTop Som heltall
Dim X, Y Som heltall
UserLft = 20
UserTop = 20
txtDataShow. Høyde = 19
txtDataShow. Bredde = 25
txtDataShow. TextAlign = _
HorizontalAlignment. Senter
txtDataShow. BorderStyle = _
Border. FixedSingle
txtDataShow. Tekst = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Høyde
txtDataShow. Plassering = nytt punkt (X, Y)
Meg. Kontroller. Legg til (txtDataShow)
Slutt sub
Sluttklasse
Veldig bra poeng, John. Dette er absolutt mye enklere enn Microsoft-koden... så jeg lurer på hvorfor de insisterte på å gjøre det på den måten?
La oss prøve å endre en av eiendomsoppgavene i koden for å starte vår undersøkelse. La oss endre
txtDataShow. Høyde = 19
til
txtDataShow. Høyde = 100
bare for å sikre at det er en merkbar forskjell.
Når vi kjører koden igjen, får vi... Whaaaat??? ... det samme. Ingen endring i det hele tatt. Faktisk kan du vise verdien med et utsagn som MsgBox (txtDataShow. Høyde), og du får fremdeles 20 som verdien av eiendommen uansett hva du tildeler den. Hvorfor skjer det?
Svaret er at vi ikke henter vår egen klasse for å lage objektene, vi legger bare ting til en annen klasse, så vi må følge reglene for den andre klassen. Og disse reglene sier at du ikke kan endre Height-egenskapen. (Wellllll... du kan. Hvis du endrer Multiline-egenskapen til True, kan du endre høyden.)
Hvorfor VB.NET går foran og kjører koden uten engang å kjenne at det kan være noe galt når det faktisk ser bort fra uttalelsen din er en hel 'nother gripe'. Jeg kan imidlertid foreslå i det minste en advarsel i samlingen. (Hint! Hint! Hint! Lytter Microsoft?)
Eksemplet fra del I arver fra en annen klasse, og dette gjør egenskapene tilgjengelige for koden i arveklassen. Endring av høyden til 100 i dette eksempelet gir oss de forventede resultatene. (En gang til... en ansvarsfraskrivelse: Når det opprettes en ny forekomst av en stor etikettkomponent, dekker den opp den gamle. For å faktisk se de nye Label-komponentene, må du legge til metodeanropet aLabel. BringToFront ()).
Dette enkle eksemplet viser at selv om vi KAN ganske enkelt legge objekter til en annen klasse (og noen ganger er dette riktig å gjøre), programmerer du kontrollen over objektene krever at vi utleder dem i en klasse og den mest organiserte måten (tør jeg si, ". NET-måten" ??) er å lage egenskaper og metoder i den nye avledede klassen for å endre tingene. John forble ikke overbevist til å begynne med. Han sa at den nye tilnærmingen hans passer til formålet hans, selv om det er begrensninger fra å ikke være "COO" (riktig objektorientert). Mer nylig skrev John imidlertid,
"... etter å ha skrevet et sett med 5 tekstbokser under kjøring, ønsket jeg å oppdatere dataene i en påfølgende del av programmet - men ingenting endret seg - de originale dataene var fremdeles der.
Jeg fant ut at jeg kunne komme meg rundt problemet ved å skrive kode for å ta av de gamle boksene og legge dem tilbake igjen med nye data. En bedre måte å gjøre det på ville være å bruke Meg. Forfriske. Men dette problemet har vakt oppmerksomheten min for behovet for å tilveiebringe en metode for å trekke fra tekstboksene og legge dem til. "
Johns kode brukte en global variabel for å holde oversikt over hvor mange kontroller som var lagt til skjemaet, så en metode ...
Private Sub Form1_Load (_
ByVal avsender som system. Objekt, _
ByVal e As System. EventArgs) _
Håndterer MyBase. Laste
CntlCnt0 = Meg. Kontroller. Telle
Slutt sub
Da kan den "siste" kontrollen fjernes ...
N = Meg. Kontroller. Telle - 1
Meg. Kontroller. FjernAt (N)
John bemerket at "dette er kanskje litt klønete."
Det er slik Microsoft holder rede på objekter i KOM OG I sin "stygge" eksempelkode over.
Jeg har nå kommet tilbake til problemet med dynamisk å lage kontroller på et skjema ved kjøretid, og jeg har sett på artiklene "Hva som skjedde med kontrollmatriser".
Jeg har laget klassene og kan nå plassere kontrollene på skjemaet slik jeg vil at de skal være.
John demonstrerte hvordan man kontrollerer plasseringen av kontroller i en gruppekasse ved å bruke de nye klassene han har begynt å bruke. Kanskje Microsoft hadde det riktig i sin "stygge" løsning tross alt!