VB.NET: Čo sa stalo s riadiacimi poľami

Ako zaobchádzať s kolekciami ovládacích prvkov vo VB.NET

Vynechanie riadiacich polí z VB.NET je výzvou pre tých, ktorí učia o poliach.





  • Už nie je možné jednoducho skopírovať ovládací prvok, napríklad textové pole, a potom ho prilepiť (raz alebo niekoľkokrát), aby sa vytvorilo pole ovládacích prvkov.
  • Kód VB.NET na vytvorenie štruktúry podobnej riadiacemu poľu bol vo všetkých knihách o VB.NET, ktoré som si kúpil online, oveľa dlhší a oveľa zložitejší. Chýba mu jednoduchosť kódovania riadiaceho poľa, ktoré sa nachádza vo VB6.

Ak sa odvolávate na knižnicu kompatibility VB6, sú v nej objekty, ktoré fungujú skoro ako riadiace polia. Ak chcete zistiť, čo tým myslím, jednoducho použite sprievodcu aktualizáciou VB.NET s programom, ktorý obsahuje ovládacie pole. Kód je opäť škaredý, ale funguje. Zlou správou je, že spoločnosť Microsoft nezaručuje, že komponenty kompatibility budú naďalej podporované a vy ich nemáte používať.

Kód VB.NET na vytváranie a používanie „riadiacich polí“ je oveľa dlhší a oveľa zložitejší.



Podľa Microsoftu, aby ste urobili niečo, čo sa čo len približuje tomu, čo môžete robiť vo VB 6, vyžaduje vytvorenie „jednoduchého komponentu, ktorý duplikuje funkčnosť riadiaceho poľa“.

Na ilustráciu potrebujete novú triedu aj hostiteľský formulár. Trieda v skutočnosti vytvára a ničí nové štítky. Úplný kód triedy je nasledujúci:



Verejná trieda LabelArray
Zdedí System.Collections.CollectionBase
Súkromný hostiteľský formulár len na čítanie ako _
System.Windows.Forms.Form
Verejná funkcia AddNewLabel() _
Ako System.Windows.Forms.Label
' Vytvorte novú inštanciu triedy Label.
Dim aLabel As New System.Windows.Forms.Label
Pridajte štítok do zbierky
' interný zoznam.
Me.List.Add(aLabel)
Pridajte štítok do kolekcie Controls
“ formulára, na ktorý odkazuje pole HostForm.
HostForm.Controls.Add(aLabel)
' Nastavte počiatočné vlastnosti pre objekt Label.
aLabel.Top = Počet * 25
aLabel.Width = 50
aLabel.Left = 140
aLabel.Tag = Ja.Počet
aLabel.Text = 'Label' & Me.Count.ToString
Vrátiť aLabel
End Function
Public Sub New( _
ByVal hostiteľ As System.Windows.Forms.Form)
HostForm = hostiteľ
Me.AddNewLabel()
End Sub
Predvolené verejné vlastníctvo iba na čítanie _
Položka (ByVal Index As Integer) As _
System.Windows.Forms.Label
Získajte
Vrátiť CType(Me.List.Item(Index), _
System.Windows.Forms.Label)
Koniec Get
Koniec vlastníctva
Public Sub Remove()
' Skontrolujte, či existuje štítok na odstránenie.
Ak Me.Count > 0 Potom
' Odstráňte posledný štítok pridaný do poľa
' z kolekcie ovládacích prvkov formulára hostiteľa.
Všimnite si použitie predvolenej vlastnosti v
' prístup k poli.
HostForm.Controls.Remove(Ja(Ja.Počet - 1))
Me.List.RemoveAt(Ja.Count - 1)
Koniec Ak
End Sub
Koniec triedy

Na ilustráciu toho, ako by sa tento kód triedy použil, môžete vytvoriť formulár, ktorý ho volá. Budete musieť použiť kód uvedený nižšie vo formulári:

|_+_|

Po prvé, toto ani v Design Time nerobí prácu, ako sme to robili vo VB 6! A po druhé, nie sú v poli, sú v kolekcii VB.NET – čo je úplne iná vec ako pole.

Dôvod, prečo VB.NET nepodporuje „riadiace pole“ VB 6, je ten, že neexistuje nič také ako „ovládacie pole“ (všimnite si zmenu úvodzoviek). VB 6 vytvára kolekciu v zákulisí a vytvára ju ako pole pre vývojárov. Nie je to však pole a okrem funkcií poskytovaných prostredníctvom IDE nad ním máte len malú kontrolu.



Na druhej strane VB.NET to nazýva tak, ako to je: zbierka objektov. A kľúče od kráľovstva odovzdajú vývojárovi tak, že celú vec vytvoria priamo pod holým nebom.

Príkladom toho, aké výhody to vývojárovi dáva, vo VB 6 museli byť ovládacie prvky rovnakého typu a museli mať rovnaký názov. Keďže sú to len objekty vo VB.NET, môžete ich vytvoriť rôznymi typmi a dať im rôzne názvy a stále ich spravovať v rovnakej kolekcii objektov.



V tomto príklade rovnaká udalosť Click spracováva dve tlačidlá a začiarkavacie políčko a zobrazuje, na ktoré sa kliklo. Urobte to v jednom riadku kódu s VB 6!

Private Sub MixedControls_Click( _
ByVal odosielateľ Ako System.Object, _
ByVal e As System.EventArgs) _
Tlačidlo rukoväte 1. Kliknite, _
Button2.Click, _
CheckBox1.Click
' Vyhlásenie nižšie musí byť jedno dlhé vyhlásenie!
Je to tu na štyroch riadkoch, aby to bolo úzke
“ dosť na to, aby sa zmestilo na webovú stránku
Label2.Text =
Microsoft.VisualBasic.Right(odosielateľ.GetType.ToString,
Len(sender.GetType.ToString) -
(InStr(sender.GetType.ToString, 'Formuláre') + 5))
End Sub



Výpočet podreťazca je trochu zložitý, ale v skutočnosti to nie je to, o čom tu hovoríme. V udalosti Click môžete urobiť čokoľvek. Môžete napríklad použiť Typ ovládacieho prvku v príkaze If na vykonanie rôznych vecí pre rôzne ovládacie prvky.

Spätná väzba skupiny Frank's Computing Studies o poliach

Frank's Study Group poskytla príklad s formulárom, ktorý má 4 štítky a 2 tlačidlá. Tlačidlo 1 vymaže štítky a tlačidlo 2 ich vyplní. Je dobré si znova prečítať Frankovu pôvodnú otázku a všimnúť si, že príklad, ktorý použil, bola slučka, ktorá sa používa na vymazanie vlastnosti Caption poľa komponentov Label. Tu je ekvivalent VB.NET tohto kódu VB 6. Tento kód robí to, čo Frank pôvodne požadoval!



|_+_|

Ak s týmto kódom zaexperimentujete, zistíte, že okrem nastavenia vlastností Labelov môžete volať aj metódy. Prečo som sa teda ja (a spoločnosť Microsoft) namáhal s vytvorením „škaredého“ kódu v časti I článku?

Musím nesúhlasiť s tým, že je to naozaj 'Control Array' v klasickom zmysle VB. Riadiace pole VB 6 je podporovaná časť syntaxe VB 6, nie len technika. V skutočnosti možno tento príklad opísať tak, že ide o pole ovládacích prvkov, nie pole ovládacích prvkov.

V časti I som sa sťažoval, že príklad Microsoftu fungoval LEN v čase spustenia a nie v čase návrhu. Môžete pridávať a odstraňovať ovládacie prvky z formulára dynamicky, ale celá vec musí byť implementovaná v kóde. Ovládacie prvky nemôžete vytvárať presúvaním myšou ako vo VB 6. Tento príklad funguje hlavne v čase návrhu a nie v čase spustenia. Počas spustenia nemôžete dynamicky pridávať a odstraňovať ovládacie prvky. Svojím spôsobom je to úplný opak príkladu z časti I.

Klasický príklad ovládacieho poľa VB 6 je ten istý, ktorý je implementovaný v kóde VB .NET. Tu v kóde VB 6 (tento je prevzatý z Mezick & Hillier, Sprievodca certifikačnými skúškami Visual Basic 6 , str. 206 - mierne upravené, pretože príklad v knihe vedie k ovládacím prvkom, ktoré nie je možné vidieť):

|_+_|

Ale ako Microsoft (a ja) súhlasíme, ovládacie polia VB 6 nie sú vo VB.NET možné. Takže najlepšie, čo môžete urobiť, je duplikovať funkčnosť. Môj článok duplikoval funkčnosť nájdenú v príklade Mezick & Hillier. Kód študijnej skupiny duplikuje funkčnosť možnosti nastavenia vlastností a volania metód.

Základom je teda to, že naozaj záleží na tom, čo chcete robiť. VB.NET nemá celú vec zabalenú ako súčasť jazyka -- zatiaľ -- ale v konečnom dôsledku je oveľa flexibilnejší.

John Fannon's Take on Control Arrays

John napísal: Potreboval som riadiace polia, pretože som chcel do formulára vložiť jednoduchú tabuľku čísel za behu. Nechcel som mať nevoľnosť z toho, že ich všetky umiestňujem jednotlivo a chcel som použiť VB.NET. Spoločnosť Microsoft ponúka veľmi podrobné riešenie jednoduchého problému, ale rozlúsknuť veľmi malý oriešok je veľmi veľká perlička. Po nejakom experimentovaní som nakoniec narazil na riešenie. Tu je návod, ako som to urobil.

Vyššie uvedený príklad About Visual Basic ukazuje, ako môžete vytvoriť textové pole vo formulári vytvorením inštancie objektu, nastavením vlastností a jeho pridaním do kolekcie Controls, ktorá je súčasťou objektu Form.

Dim txtDataShow As New TextBox
txtDataShow.Height = 19
txtDataShow.Width = 80
txtDataShow.Location = Nový bod (X, Y)
Me.Controls.Add(txtDataShow)
Hoci riešenie Microsoftu vytvára triedu, usúdil som, že by bolo možné namiesto toho všetko zabaliť do podprogramu. Zakaždým, keď zavoláte tento podprogram, vytvoríte novú inštanciu textového poľa vo formulári. Tu je úplný kód:

Formulár verejnej triedy1
Zdedí System.Windows.Forms.Form

#Region ' Kód vygenerovaný nástrojom Windows Form Designer '

Private Sub BtnStart_Click( _
ByVal odosielateľ Ako System.Object, _
ByVal e As System.EventArgs) _
Rukoväte btnStart.Click

Dim I As Integer
Dim sData As String
Pre I = 1 až 5
sData = CStr(I)
Zavolajte AddDataShow(sData, I)
Ďalšie
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 ako celé číslo
UserLft = 20
UserTop = 20
txtDataShow.Height = 19
txtDataShow.Width = 25
txtDataShow.TextAlign = _
HorizontalAlignment.Center
txtDataShow.BorderStyle = _
BorderStyle.FixedSingle
txtDataShow.Text = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow.Height
txtDataShow.Location = Nový bod (X, Y)
Me.Controls.Add(txtDataShow)
End Sub
Koniec triedy
Veľmi dobrá poznámka, John. Toto je určite oveľa jednoduchšie ako kód Microsoftu ... tak by ma zaujímalo, prečo trvali na tom, aby to urobili takto?

Ak chcete začať naše vyšetrovanie, skúsme zmeniť jedno z priradení vlastností v kóde. Poďme sa zmeniť

txtDataShow.Height = 19
do

txtDataShow.Height = 100
len aby sme sa uistili, že je tam viditeľný rozdiel.

Keď znova spustíme kód, dostaneme ... Čože??? ... to isté. Vôbec žiadna zmena. V skutočnosti môžete hodnotu zobraziť pomocou príkazu ako MsgBox (txtDataShow.Height) a stále dostanete 20 ako hodnotu vlastnosti bez ohľadu na to, čo jej priradíte. Prečo sa to deje?

Odpoveď je, že na vytváranie objektov neodvodzujeme vlastnú triedu, ale iba pridávame veci do inej triedy, takže musíme dodržiavať pravidlá inej triedy. A tieto pravidlá uvádzajú, že nemôžete zmeniť vlastnosť Výška. (No... môžete. Ak zmeníte vlastnosť Multiline na True, potom môžete zmeniť výšku.)

Prečo VB.NET pokračuje a spúšťa kód bez toho, aby čo i len zakňučal, že by mohlo byť niečo v neporiadku, keď v skutočnosti úplne ignoruje vaše vyhlásenie, je úplne iná hádka. Mohol by som však navrhnúť aspoň varovanie v kompilácii. (Tip! Tip! Tip! Počúva vás Microsoft?)

Príklad z časti I dedí z inej triedy a to sprístupňuje vlastnosti kódu v dediacej triede. Zmena vlastnosti Výška na 100 v tomto príklade nám dáva očakávané výsledky. (Opäť ... jedno upozornenie: Keď sa vytvorí nová inštancia veľkého komponentu Label, prekryje starú. Ak chcete skutočne vidieť nové komponenty Label, musíte pridať volanie metódy aLabel.BringToFront().)

Tento jednoduchý príklad ukazuje, že hoci môžeme jednoducho pridať objekty do inej triedy (a niekedy je to správna vec), programovanie kontroly nad objektmi vyžaduje, aby sme ich odvodili v triede a čo najorganizovanejšie (dovolím si povedať, 'cesta .NET' ??) je vytvoriť vlastnosti a metódy v novej odvodenej triede na zmenu vecí. John zostal najprv nepresvedčený. Povedal, že jeho nový prístup vyhovuje jeho účelu, aj keď existujú obmedzenia z toho, že nie je „COO“ (správne objektovo orientovaný). Nedávno však John napísal,

' ... po napísaní sady 5 textových polí za behu som chcel aktualizovať údaje v nasledujúcej časti programu - ale nič sa nezmenilo - pôvodné údaje tam stále boli.

Zistil som, že by som mohol problém obísť napísaním kódu na odstránenie starých škatúľ a ich vložením späť s novými údajmi. Lepší spôsob, ako to urobiť, by bolo použiť Me.Refresh. Tento problém ma však upozornil na potrebu poskytnúť metódu na odčítanie textových polí, ako aj na ich sčítanie.“

Johnov kód používal globálnu premennú na sledovanie toho, koľko ovládacích prvkov bolo pridaných do formulára, takže metóda ...

Private Sub Form1_Load( _
ByVal odosielateľ Ako System.Object, _
ByVal e As System.EventArgs) _
Rukoväte MyBase.Load
CntlCnt0 = Me.Controls.Count
End Sub

Potom mohol byť „posledný“ ovládací prvok odstránený...

N = Me.Controls.Count - 1
Me.Controls.RemoveAt(N)
John poznamenal, že 'možno je to trochu nemotorné'.

Je to spôsob, akým spoločnosť Microsoft sleduje objekty v COM A v ich „škaredom“ príklade kódu vyššie.

Teraz som sa vrátil k problému dynamického vytvárania ovládacích prvkov vo formulári v čase spustenia a znova som sa pozrel na články „Čo sa stalo s ovládacími poľami“.

Vytvoril som triedy a teraz môžem umiestniť ovládacie prvky do formulára tak, ako chcem, aby boli.

John predviedol, ako ovládať umiestnenie ovládacích prvkov v skupinovom boxe pomocou nových tried, ktoré začal používať. Možno to mal Microsoft vo svojom „škaredom“ riešení predsa len správne!