VB.NET: Co se stalo s kontrolními poli

Vynechání kontrolních polí z VB.NET je výzvou pro ty, kdo učí o polích.

  • Již není možné jednoduše zkopírovat ovládací prvek, například textové pole, a poté jej vložit (jednou nebo několikrát) a vytvořit ovládací pole.
  • Kód VB.NET pro vytvoření struktury podobné ovládacímu poli byl ve všech knihách o VB.NET, které jsem koupil a online, mnohem delší a mnohem složitější. Postrádá jednoduchost kódování řídicího pole, které se nachází ve VB6.

Pokud odkazujete na knihovnu kompatibility VB6, jsou tam objekty, které fungují podobně jako kontrolní pole. Chcete-li vidět, co tím myslím, jednoduše použijte průvodce upgradem VB.NET s programem, který obsahuje kontrolní pole. Kód je opět ošklivý, ale funguje. Špatnou zprávou je, že společnost Microsoft nezaručuje, že komponenty kompatibility budou nadále podporovány a neměli byste je používat.

Kód VB.NET pro vytváření a používání „kontrolních polí“ je mnohem delší a mnohem složitější.

Podle Microsoftu udělat něco, co se blíží tomu, co můžete udělat ve VB 6, vyžaduje vytvoření „jednoduché komponenty, která duplikuje funkce ovládacího pole“.

instagram viewer

K ilustraci potřebujete novou třídu i hostitelský formulář. Třída ve skutečnosti vytváří a ničí nové štítky. Úplný kód třídy je následující:

Public Class LabelArray
Zdědí systém. Sbírky. CollectionBase
Private ReadOnly HostForm As _
Systém. Okna. Formuláře. Formulář
Veřejná funkce AddNewLabel () _
Jako systém. Okna. Formuláře. Označení
'Vytvořte novou instanci třídy Label.
Dim aLabel jako nový systém. Okna. Formuláře. Označení
„Přidejte popisek do sbírky
vnitřní seznam.
Mě. Seznam. Přidat (aLabel)
'Přidejte štítek do kolekce Controls
'formuláře, na který odkazuje pole HostForm.
HostForm. Řízení. Přidat (aLabel)
'Nastavit vnitřní vlastnosti objektu Label.
štítek. Top = Count * 25
štítek. Šířka = 50
štítek. Vlevo = 140
štítek. Tag = Me. Počet
štítek. Text = "Label" & Me. Počet. ToString
Vraťte aLabel
Ukončit funkci
Public Sub New (_
ByVal hostitel jako systém. Okna. Formuláře. Formulář)
HostForm = hostitel
Mě. AddNewLabel ()
End Sub
Výchozí veřejná vlastnost ReadOnly _
Položka (index ByVal jako celé číslo) jako _
Systém. Okna. Formuláře. Označení
Dostat
Vrátit CType (Me. List. Položka (Index), _
Systém. Okna. Formuláře. Označení)
End Get
Ukončit vlastnost
Odebrání veřejných podřízených ()
„Zkontrolujte, zda existuje štítek, který chcete odstranit.
Pokud mě. Počet> 0 Pak
„Odstraňte poslední štítek přidaný do pole
'z kolekce ovládacích prvků hostitelského formuláře.
'Všimněte si použití výchozí vlastnosti v
'přístup do pole.
HostForm. Řízení. Odebrat (Me (Me. Počet - 1))
Mě. Seznam. RemoveAt (počet osob - 1)
Konec If
End Sub
Koncová třída

Pro ilustraci, jak bude tento kód třídy použit, můžete vytvořit formulář, který jej volá. Budete muset použít níže uvedený kód ve tvaru:

Formulář veřejné třídy1. Zdědí systém. Okna. Formuláře. Formulář. #Region "Generovaný kód Windows Form Designer" 'Musíte také přidat příkaz:' MyControlArray = New LabelArray (Me) 'po volání InitializeComponent () v. 'skrytý kód regionu. 'Vyhlásit nový objekt ButtonArray. Dim MyControlArray jako LabelArray. Soukromý díl btnLabelAdd_Click (_. Odesílatel ByVal jako systém. Objekt, _. ByVal e As System. EventArgs) _. Popisuje btnLabelAdd. Klikněte na. 'Volejte metodu AddNewLabel. 'MyControlArray. MyControlArray. AddNewLabel () 'Změňte vlastnost BackColor. tlačítka 0. MyControlArray (0) .BackColor = _. Systém. Výkres. Barva. Červené. End Sub. Soukromý díl btnLabelRemove_Click (_. Odesílatel ByVal jako systém. Objekt, _. ByVal e As System. EventArgs) _. Úchyty btnLabelRemove. Klikněte na. 'Volejte metodu Odebrat z MyControlArray. MyControlArray. Odstranit() End Sub. Koncová třída

Nejprve to ani v Design Time nedělá práci, jako jsme to dělali ve VB 6! A za druhé, nejsou v poli, jsou ve sbírce VB.NET - mnohem jiná věc než pole.

Důvod VB.NET nepodporuje VB 6 "kontrolní pole" je, že neexistuje nic jako "kontrolní" pole "(všimněte si změny uvozovek). VB 6 vytváří kolekci zákulisí a vytváří ji jako pole pro vývojáře. Ale nejde o pole a máte nad tím malou kontrolu nad funkcemi poskytovanými prostřednictvím IDE.

Na druhou stranu to VB.NET nazývá to, co to je: kolekce objektů. A předávají klíče do království vývojáři tím, že celou věc vytvářejí přímo venku.

Jako příklad druhu výhod to dává vývojáři, ve VB 6 musely být ovládací prvky stejného typu a musely mít stejné jméno. Protože se jedná o pouze objekty ve VB.NET, můžete je vytvořit různými typy a dát jim různá jména a stále je spravovat ve stejné sbírce objektů.

V tomto příkladu stejná událost Click zpracovává dvě tlačítka a zaškrtávací políčko a zobrazuje, na které z nich bylo kliknuto. Udělejte to v jednom řádku kódu s VB 6!

Private Sub MixedControls_Click (_
Odesílatel ByVal jako systém. Objekt, _
ByVal e As System. EventArgs) _
Kliky Button1.Click, _
Button2.Click, _
CheckBox1.Click
„Níže uvedené prohlášení musí být jedno dlouhé prohlášení!
"Je to tady na čtyřech řádcích, abych to udržel úzký."
'dost, aby se vešly na webovou stránku
Label2.Text =
Microsoft. VisualBasic. Vpravo (odesílatel. GetType. ToString,
Len (odesílatel. GetType. ToString) -
(InStr (odesílatel. GetType. ToString, „Formuláře“) + 5))
End Sub

Výpočet podřetězce je trochu složitý, ale ve skutečnosti to není o čem mluvíme. V události Click byste mohli udělat cokoli. Můžete například použít typ ovládacího prvku v příkazu If k provádění různých věcí pro různé ovládací prvky.

Frank's Computing Studies Group Feedback on Arrays

Frankova studijní skupina poskytla příklad s formulářem, který má 4 štítky a 2 tlačítka. Tlačítko 1 vymaže štítky a tlačítko 2 je vyplní. Je to dobrý nápad znovu si přečíst Frankovu původní otázku a všimnout si, že příkladem, který použil, byla smyčka, která se používá k vymazání vlastnosti Caption řady komponent Label. Zde je ekvivalent VB.NET tohoto kódu VB 6. Tento kód dělá to, co Frank původně požadoval!

Formulář veřejné třídy1. Zdědí systém. Okna. Formuláře. Formulář. #Region "Generovaný kód Windows Form Designer" Dim LabelArray (4) Jako štítek. 'deklarovat řadu štítků. Private Sub Form1_Load (_. Odesílatel ByVal jako systém. Objekt, _. ByVal e As System. EventArgs) _. Popisuje MyBase. Zatížení. SetControlArray () End Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. End Sub. Private Sub Button1_Click (_. Odesílatel ByVal jako systém. Objekt, _. ByVal e As System. EventArgs) _. Kliky Button1.Click. 'Tlačítko 1 Vymazat pole. Dim a In Inger. Pro a = 1 až 4. LabelArray (a) .Text = "" Další. End Sub. Private Sub Button2_Click (_. Odesílatel ByVal jako systém. Objekt, _. ByVal e As System. EventArgs) _. Kliky Button2.Click. 'Tlačítko 2 Vyplňte pole. Dim a In Inger. Pro a = 1 až 4. LabelArray (a) .Text = _. „Control Array“ a CStr (a) Další. End Sub. Koncová třída

Pokud experimentujete s tímto kódem, zjistíte, že kromě nastavení vlastností štítků můžete také volat metody. Proč jsem tedy (a Microsoft) narazil na všechny potíže s vytvořením kódu „ošklivého“ v části I článku?

Musím nesouhlasit, že se jedná o „kontrolní pole“ v klasickém smyslu VB. Ovládací pole VB 6 je podporovanou součástí syntaxe VB 6, ne jen technikou. Ve skutečnosti je možná způsob, jak tento příklad popsat, že se jedná o pole ovládacích prvků, nikoli o kontrolní pole.

V části I jsem si stěžoval, že příklad společnosti Microsoft fungoval POUZE v době běhu a nikoli v době návrhu. Ovládací prvky z formuláře můžete přidávat a mazat dynamicky, ale celá věc musí být implementována v kódu. Ovládací prvky nelze přetahovat a vytvářet tak, jak je to možné ve VB 6. Tento příklad funguje hlavně v době návrhu a nikoli v době spuštění. V době spuštění nelze dynamicky přidávat ani mazat ovládací prvky. Svým způsobem je to úplný opak příkladu I.

Příklad klasického ovládacího pole VB 6 je stejný jako v kódu VB .NET. Tady v kódu VB 6 (převzato z Mezick & Hillier, Příručka pro certifikační zkoušky jazyka Visual Basic 6, str. 206 - mírně upraveno, protože příklad v knize vede k ovládacím prvkům, které nelze vidět):

Dim MyTextBox jako VB.TextBox. Statické intNumber jako celé číslo. intNumber = intNumber + 1. Nastavit MyTextBox = _. Mě. Řízení. Přidat ("VB.TextBox", _. „Text“ a intNumber) MyTextBox. Text = MyTextBox. Název. MyTextBox. Viditelné = Pravda. MyTextBox. Vlevo = _. (intNumber - 1) * 1200

Ale jak Microsoft (a já) souhlasím, ovládací prvky VB 6 nejsou ve VB.NET možné. To nejlepší, co můžete udělat, je duplikovat funkčnost. Můj článek duplikoval funkce nalezené v příkladu Mezick & Hillier. Kód studijní skupiny duplikuje funkčnost možnosti nastavit vlastnosti a metody volání.

Pointa je, že to opravdu záleží na tom, co chcete dělat. VB.NET nemá celou věc zabalenou jako součást jazyka - Přesto - ale nakonec je mnohem flexibilnější.

John Fannon's Take on Control Arrays

John napsal: Potřeboval jsem kontrolní pole, protože jsem chtěl dát jednoduchou tabulku čísel do formuláře v době běhu. Nechtěl jsem nevolnost jejich umístění jednotlivě a chtěl jsem použít VB.NET. Microsoft nabízí velmi podrobné řešení jednoduchého problému, ale je to velmi velké kladivo prasknout velmi malou matici. Po nějakém experimentování jsem nakonec narazil na řešení. Takhle jsem to udělal.

Výše uvedený příklad About Visual Basic ukazuje, jak můžete vytvořit textové pole ve formuláři vytvořením instance objektu, nastavení vlastností a přidání do kolekce Controls, která je součástí formuláře objekt.

Dim txtDataShow jako nové textové pole
txtDataShow. Výška = 19
txtDataShow. Šířka = 80
txtDataShow. Umístění = Nový bod (X, Y)
Mě. Řízení. Přidat (txtDataShow)
Přestože řešení společnosti Microsoft vytváří třídu, zdůvodnil jsem, že by bylo možné namísto toho vše zabalit do podprogramu. Při každém volání této podprogramy vytvoříte novou instanci textového pole ve formuláři. Zde je kompletní kód:

Formulář veřejné třídy1
Zdědí systém. Okna. Formuláře. Formulář

#Region "Generovaný kód Windows Form Designer"

Private Sub BtnStart_Click (_
Odesílatel ByVal jako systém. Objekt, _
ByVal e As System. EventArgs) _
Kliky btnStart. Klikněte na

Dim I As Integer
Dim sData jako řetězec
Pro I = 1 až 5
sData = CStr (I)
Volání AddDataShow (sData, I)
další
End Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I jako celé číslo)

Dim txtDataShow jako nové textové pole
Dim UserLft, UserTop jako celé číslo
Dim X, Y jako celé číslo
UserLft = 20
UserTop = 20
txtDataShow. Výška = 19
txtDataShow. Šířka = 25
txtDataShow. TextAlign = _
Horizontální zarovnání. Centrum
txtDataShow. BorderStyle = _
BorderStyle. FixedSingle
txtDataShow. Text = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Výška
txtDataShow. Umístění = Nový bod (X, Y)
Mě. Řízení. Přidat (txtDataShow)
End Sub
Koncová třída
Velmi dobrý bod, Johne. To je určitě mnohem jednodušší než kód Microsoft... tak jsem zvědavý, proč na tom tak trvali?

Chcete-li začít s vyšetřováním, zkusme změnit jednu z přiřazení vlastností v kódu. Pojďme se změnit

txtDataShow. Výška = 19
na

txtDataShow. Výška = 100
jen aby se ujistil, že je zde znatelný rozdíl.

Když znovu spustíme kód, dostaneme... Whaaaat??? ... ta samá věc. Žádná změna vůbec. Ve skutečnosti můžete zobrazit hodnotu pomocí příkazu jako MsgBox (txtDataShow). Výška) a stále dostanete 20 jako hodnotu vlastnosti bez ohledu na to, co jí přiřadíte. Proč se to stalo?

Odpověď zní, že nevyvíjíme vlastní třídu pro vytváření objektů, pouze přidáváme věci do jiné třídy, takže se musíme řídit pravidly jiné třídy. A tato pravidla uvádějí, že nemůžete změnit vlastnost Výška. (Dobře... můžeš. Pokud změníte vlastnost Multiline na True, pak můžete změnit výšku.)

Proč VB.NET jde dopředu a vykonává kód, aniž by zakňučel, že by mohlo dojít k něčemu špatnému, když ve skutečnosti zcela ignoruje vaše tvrzení, což je celá 'nother gripe'. Mohl bych však navrhnout alespoň varování v kompilaci. (Náznak! Náznak! Náznak! Poslouchá Microsoft?)

Příklad z části I dědí z jiné třídy, a tím zpřístupní vlastnosti kódu v zděděné třídě. Změnou vlastnosti Výška na 100 v tomto příkladu získáte očekávané výsledky. (Znovu... jedno vyloučení odpovědnosti: Když je vytvořena nová instance velké komponenty Label, zakrývá starou. Chcete-li skutečně vidět nové komponenty Label, musíte přidat volání metody aLabel. BringToFront ().)

Tento jednoduchý příklad ukazuje, že ačkoli můžeme jednoduše přidat objekty do jiné třídy (a někdy je to správná věc), programovací ovládání objektů vyžaduje, abychom je odvodili ve třídě a nejorganizovanějším způsobem (odvažuji se říkat „.NET cesta“ ??) je vytvoření vlastností a metod v nové odvozené třídě, která se má změnit věci. John zůstal zpočátku nepřesvědčen. Řekl, že jeho nový přístup vyhovuje jeho účelu, i když existují určitá omezení, než aby nebyli „COO“ (správně orientovaný na objekt). Nedávno však John napsal,

"... Po napsání sady 5 textových polí za běhu jsem chtěl aktualizovat data v následné části programu - ale nic se nezměnilo - původní data tam stále byla.

Zjistil jsem, že dokážu problém vyřešit tím, že napíšu kód, který odstraním staré krabice a vrátím je zpět s novými daty. Lepším způsobem, jak toho dosáhnout, by bylo použít mě. Obnovit. Tento problém však upoutal mou pozornost na potřebu poskytnout metodu odečtení textových polí a jejich přidání. “

Johnův kód používal globální proměnnou, aby sledoval, kolik ovládacích prvků bylo přidáno do formuláře, takže metoda ...

Private Sub Form1_Load (_
Odesílatel ByVal jako systém. Objekt, _
ByVal e As System. EventArgs) _
Popisuje MyBase. Zatížení
CntlCnt0 = Me. Řízení. Počet
End Sub

Poté mohl být „poslední“ ovládací prvek odstraněn ...

N = Me. Řízení. Počet - 1
Mě. Řízení. RemoveAt (N)
John poznamenal, že „možná je to trochu nemotorné.“

Je to způsob, jakým společnost Microsoft sleduje objekty v COM A v jejich „ošklivém“ příkladu výše.

Nyní jsem se vrátil k problému dynamického vytváření ovládacích prvků ve formuláři za běhu a znovu jsem se díval na články „Co se stalo s ovládacími poli“.

Vytvořil jsem třídy a nyní umísťuji ovládací prvky do formuláře tak, jak chci.

John předvedl, jak ovládat umístění ovládacích prvků do skupinového boxu pomocí nových tříd, které začal používat. Možná, že Microsoft měl koneckonců pravdu ve svém „ošklivém“ řešení!