VB.NET: Какво се случи с контролните масиви

click fraud protection

Пропускането на контролни масиви от VB.NET е предизвикателство за преподавателите за масиви.

  • Вече не е възможно просто да копирате контрола, например текстово поле, и след това да го поставите (веднъж или няколко пъти), за да създадете контролен масив.
  • Кодът VB.NET за създаване на структура, подобна на контролен масив, беше във всички книги на VB.NET, които съм купил и онлайн, много по-дълъг и много по-сложен. Липсва простотата на кодиране на контролен масив, който се намира в VB6.

Ако се позовавате на библиотеката за съвместимост на VB6, там има обекти, които действат почти като контролни масиви. За да видите какво имам предвид, просто използвайте съветника за надстройване на VB.NET с програма, която съдържа контролен масив. Кодът отново е грозен, но работи. Лошата новина е, че Microsoft няма да гарантира, че компонентите за съвместимост ще продължат да се поддържат, а вие не трябва да ги използвате.

Кодът VB.NET за създаване и използване на "контролни масиви" е много по-дълъг и много по-сложен.

instagram viewer

Според Microsoft, за да направите нещо дори близко до това, което можете да направите във VB 6, изисква създаването на „прост компонент, който дублира функционалността на контролния масив“.

Имате нужда както от нов клас, така и от хостинг формуляр, за да илюстрирате това. Класът всъщност създава и унищожава нови етикети. Пълният код на класа е както следва:

Публичен клас LabelArray
Наследствена система. Колекции. CollectionBase
Частна форма за четене само като _
Система. Windows. Форми. форма
Публична функция AddNewLabel () _
Като система. Windows. Форми. етикет
„Създайте нов екземпляр от класа Label.
Dim aLabel като нова система. Windows. Форми. етикет
„Добавете етикета към колекциите
'вътрешен списък.
Мен. Списък. Добавяне (aLabel)
„Добавете етикета към колекцията Controls
на формуляра, посочен от полето HostForm.
HostForm. Контроли. Добавяне (aLabel)
„Задайте входни свойства за обекта Label.
aLabel. Най-горе = Брой * 25
aLabel. Ширина = 50
aLabel. Ляво = 140
aLabel. Маркер = аз. Броя
aLabel. Text = "Етикет" & Аз. Броя. ToString
Върнете aLabel
Крайна функция
Обществен под нов (_
ByVal хост като система. Windows. Форми. Form)
HostForm = хост
Мен. AddNewLabel ()
Край Sub
Публична собственост ReadOnly по подразбиране _
Елемент (ByVal индекс като цяло число) като _
Система. Windows. Форми. етикет
получавам
Върнете CType (Ме. Списък. Елемент (индекс), _
Система. Windows. Форми. Label)
Край Вземете
Крайна собственост
Публично премахване на Sub ()
„Проверете, за да сте сигурни, че има етикет за премахване.
Ако Аз. Брой> 0 Тогава
„Извадете последния етикет, добавен към масива
'от колекцията за контрол на хост формуляра.
„Забележете използването на свойството по подразбиране в
'достъп до масива.
HostForm. Контроли. Премахване (Аз (Брой. Аз - 1))
Мен. Списък. RemoveAt (Брой на мен - 1)
Край Ако
Край Sub
Краен клас

За да илюстрирате как би се използвал този клас клас, можете да създадете формуляр, който го извиква. Ще трябва да използвате кода, показан по-долу във формата:

Форма за публичен клас1. Наследствена система. Windows. Форми. Форма. #Region "Код на генериран от дизайнера формуляр на Windows" „Също така трябва да добавите изявлението:„ MyControlArray = New LabelArray (Me) 'след повикване InitializeComponent () в. 'скрит код на региона. „Обявете нов обект ButtonArray. Dim MyControlArray като LabelArray. Частен Sub btnLabelAdd_Click (_. ByVal подател като система. Обект, _. ByVal e като система. EventArgs) _. Дръжки btnLabelAdd. Кликнете. „Обадете се на метода AddNewLabel. на MyControlArray. MyControlArray. AddNewLabel () „Променете свойството BackColor. 'на бутона 0. MyControlArray (0) .BackColor = _. Система. Рисуване. Цвят. Червен. Край Sub. Частен Sub btnLabelRemove_Click (_. ByVal подател като система. Обект, _. ByVal e като система. EventArgs) _. Дръжки btnLabelRemove. Кликнете. „Обадете се на метода за премахване на MyControlArray. MyControlArray. Премахване() Край Sub. Краен клас

Първо, това дори не върши работа в Design Time, както сме го правили в VB 6! И второ, те не са в масив, те са в колекция VB.NET - много по-различно нещо от масив.

Причината VB.NET да не поддържа VB 6 "контролен масив" е, че няма такова нещо като "control" "масив" (обърнете внимание на промяната на кавичките). VB 6 създава колекция зад кулисите и я прави да се показва като масив на разработчика. Но това не е масив и имате малък контрол върху него извън функциите, предоставени чрез IDE.

VB.NET, от друга страна, го нарича какво е: колекция от обекти. И предават ключовете от кралството на предприемача, като създават цялото нещо на открито.

Като пример за вида на предимствата, които това дава на разработчика, в VB 6 контролите трябва да са от същия тип и те трябва да имат същото име. Тъй като това са само обекти във VB.NET, можете да ги правите различни видове и да им давате различни имена и пак да ги управлявате в една и съща колекция от обекти.

В този пример същото събитие Click обработва два бутона и квадратче за отметка и показва кой е щракнат. Направете това в един ред код с VB 6!

Частен Sub MixedControls_Click (_
ByVal подател като система. Обект, _
ByVal e като система. EventArgs) _
Дръжки Button1.Click, _
Бутон2.Клик, _
CheckBox1.Click
„Изявлението по-долу трябва да бъде едно дълго изявление!
- Тук има четири линии, за да е тясно
'достатъчно, за да се побере в уеб страница
Label2.Text =
Microsoft. VisualBasic. Право (подател. GetType. ToString,
Лен (подател. GetType. ToString) -
(InStr (подател) GetType. ToString, „Форми“) + 5))
Край Sub

Изчислението на подредовете е някак сложно, но всъщност не става дума за това. Можете да направите всичко в събитието Click. Можете например да използвате Type of the control в оператор If, за да правите различни неща за различни контроли.

Отзиви за групови изследвания на Франк за проучвания на компютърни масиви

Изучителната група на Франк даде пример с формуляр, който има 4 етикета и 2 бутона. Бутон 1 изчиства етикетите, а бутон 2 ги запълва. Добра идея е отново да прочетете първоначалния въпрос на Франк и да забележите, че примерът, който използва, е цикъл, който се използва за изчистване на свойството Caption на масив от компоненти на Label. Ето еквивалента на VB.NET на този код VB 6. Този код прави това, което Франк първоначално поиска!

Форма за публичен клас1. Наследствена система. Windows. Форми. Форма. #Region "Код на генериран от дизайнера формуляр на Windows" Dim LabelArray (4) Като етикет. 'обявява масив от етикети. Private Sub Form1_Load (_. ByVal подател като система. Обект, _. ByVal e като система. EventArgs) _. Работи с MyBase. Заредете. SetControlArray () Край Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. Край Sub. Частен подбутон1_Click (_. ByVal подател като система. Обект, _. ByVal e като система. EventArgs) _. Дръжки Button1.Click. „Бутон 1 Изчисти масив. Dim a като цяло число. За а = 1 до 4. LabelArray (a) .Text = "" Следващия. Край Sub. Частен подбутон2_Click (_. ByVal подател като система. Обект, _. ByVal e като система. EventArgs) _. Дръжки Button2.Click. „Бутон 2 Запълване на масив. Dim a като цяло число. За а = 1 до 4. LabelArray (a) .Text = _. „Контролен масив“ и CStr (a) Следващия. Край Sub. Краен клас

Ако експериментирате с този код, ще откриете, че в допълнение към настройването на свойствата на етикетите, можете да извиквате и методи. Така че защо аз (и Microsoft) отидох на всички проблеми, за да изградя "Ugly" код в част I на статията?

Трябва да не съм съгласен, че това наистина е „Control Array“ в класическия VB смисъл. VB 6 Control Array е поддържана част от синтаксиса на VB 6, а не само техника. Всъщност може би начинът да се опише този пример е, че това е масив от контроли, а не контролен масив.

В част I се оплаках, че примерът на Microsoft САМО е работил по време на изпълнение и не е проектиран. Можете да добавяте и изтривате контроли от формуляр динамично, но цялата работа трябва да бъде внедрена в код. Не можете да плъзгате и пускате контроли, за да ги създадете както можете във VB 6. Този пример работи главно по време на проектиране, а не по време на изпълнение. Не можете да добавяте и изтривате контроли динамично по време на изпълнение. По някакъв начин това е пълната противоположност на примера на част I.

Класическият пример за контролен масив VB 6 е същият, който се реализира в кода VB .NET. Тук в кода на VB 6 (това е взето от Mezick & Hillier, Visual Basic 6 Ръководство за изпит за сертифициране, стр. 206 - леко променен, тъй като примерът в книгата води до контроли, които не могат да се видят):

Dim MyTextBox като VB.TextBox. Статичен intNumber като цяло число. intNumber = intNumber + 1. Задайте MyTextBox = _. Мен. Контроли. Добавяне („VB.TextBox“, _. „Текст“ и intNumber) MyTextBox. Текст = MyTextBox. Name. MyTextBox. Видимо = Вярно. MyTextBox. Ляво = _. (intNumber - 1) * 1200

Но както Microsoft се съгласява (и аз), VB 6 контролните масиви не са възможни във VB.NET. Така че най-доброто, което можете да направите, е да дублирате функционалността. Моята статия дублира функционалността, намерена в примера на Mezick & Hillier. Кодът на изследователската група дублира функционалността на възможността да задавате свойства и методи за повикване.

Така че долният ред е, че наистина зависи от това, което искате да направите. VB.NET няма всичко, което е обвито като част от езика - все пак - но в крайна сметка е далеч по-гъвкав.

Джон Фанън поема контролни масиви

Джон пише: имах нужда от контролни масиви, защото исках да поставя обикновена таблица от числа във формуляр по време на изпълнение. Не исках гаденето да ги поставя всички поотделно и исках да използвам VB.NET. Microsoft предлага много подробно решение на опростен проблем, но е много голям кувалда за напукване на много малка гайка. След някои експерименти най-накрая попаднах на решение. Ето как го направих.

Примерът About Visual Basic по-горе показва как можете да създадете TextBox във формуляр чрез създаване на екземпляр на обекта, задаване на свойства и добавянето му към колекцията Controls, която е част от Form обект.

Dim txtDataShow като нов TextBox
txtDataShow. Височина = 19
txtDataShow. Ширина = 80
txtDataShow. Местоположение = Нова точка (X, Y)
Мен. Контроли. Добавяне (txtDataShow)
Въпреки че решението на Microsoft създава клас, разсъждавах, че би било възможно вместо това всичко да се увие в подпрограма. Всеки път, когато се обадите на тази подпрограма, създавате нов екземпляр на текстовото поле във формата. Ето пълния код:

Форма за публичен клас1
Наследствена система. Windows. Форми. форма

#Region "Код на генериран от дизайнера формуляр на Windows"

Частен Sub BtnStart_Click (_
ByVal подател като система. Обект, _
ByVal e като система. EventArgs) _
Дръжки btnStart. Кликнете

Dim I като цяло
Dim sData като низ
За I = 1 до 5
sData = CStr (I)
Обадете се на AddDataShow (sData, I)
Следващия
Край Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I като цяло)

Dim txtDataShow като нов TextBox
Dim UserLft, UserTop As Integer
Dim X, Y като цяло число
UserLft = 20
UserTop = 20
txtDataShow. Височина = 19
txtDataShow. Ширина = 25
txtDataShow. TextAlign = _
HorizontalAlignment. център
txtDataShow. BorderStyle = _
BorderStyle. FixedSingle
txtDataShow. Текст = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. височина
txtDataShow. Местоположение = Нова точка (X, Y)
Мен. Контроли. Добавяне (txtDataShow)
Край Sub
Краен клас
Много добра точка, Джон. Това със сигурност е много по-просто от кода на Microsoft... така че се чудя защо те настояха да го направят по този начин?

За да започнем нашето разследване, нека опитаме да променим едно от заданията на свойствата в кода. Нека се променим

txtDataShow. Височина = 19
да се

txtDataShow. Височина = 100
само за да се уверите, че има забележима разлика.

Когато отново стартираме кода, получаваме... Whaaaat??? ... едно и също нещо. Никаква промяна. Всъщност можете да покажете стойността с оператор като MsgBox (txtDataShow). Височина) и все още получавате 20 като стойност на свойството, независимо какво му възлагате. Защо това се случва?

Отговорът е, че ние не извеждаме собствен клас за създаване на обекти, ние просто добавяме нещата към друг клас, така че трябва да следваме правилата на другия клас. И тези правила гласи, че не можете да промените свойството Height. (Wellllll... можеш. Ако промените свойството Multiline на True, тогава можете да промените Height.)

Защо VB.NET върви напред и изпълнява кода, без дори хленчене, че може да има нещо нередно, когато всъщност тотално пренебрегва вашето твърдение, е цялостно. Мога обаче да предложа поне предупреждение в компилацията. (Съвет! Съвет! Съвет! Слуша ли Microsoft?)

Примерът от част I наследява от друг клас и това прави свойствата достъпни за кода в наследяващия клас. Промяната на свойството Height на 100 в този пример ни дава очакваните резултати. (Отново... един отказ от отговорност: Когато се създаде нов екземпляр от голям компонент Label, той покрива стария. За да видите действително новите компоненти на Label, трябва да добавите метода call aLabel. BringToFront ().)

Този прост пример показва, че въпреки че МОЖЕМО просто да добавим обекти в друг клас (и понякога това е правилното нещо), програмирането на контрол върху обектите изисква да ги изведем по клас и по най-организирания начин (смея ли да кажа, „начинът на .NET“ ??) е да създадем свойства и методи в новия производен клас, който да променим неща. Джон в началото остана неубеден. Той каза, че новият му подход отговаря на целта му, въпреки че има ограничения да не бъде „COO“ (правилно ориентиран към обекта). Наскоро обаче Джон пише,

"... след като написах набор от 5 текстови полета по време на изпълнение, исках да актуализирам данните в следваща част от програмата - но нищо не се промени - оригиналните данни все още бяха там.

Открих, че мога да преодолея проблема, като напиша код, за да сваля старите кутии и да ги върна отново с нови данни. По-добър начин да го направите ще бъде да Ме използвате. Освежете. Но този проблем привлече вниманието ми за необходимостта да се предостави метод за изваждане на текстовите полета, както и добавянето им. "

Кодът на Джон използва глобална променлива, за да следи колко контроли са били добавени във формата, така че метод ...

Private Sub Form1_Load (_
ByVal подател като система. Обект, _
ByVal e като система. EventArgs) _
Работи с MyBase. натоварване
CntlCnt0 = Аз. Контроли. Броя
Край Sub

Тогава "последният" контрол може да бъде премахнат ...

N = Аз. Контроли. Брой - 1
Мен. Контроли. RemoveAt (N)
Джон отбеляза, че „може би това е малко тромаво“.

Това е начинът, по който Microsoft следи обектите в COM AND в техния „грозен“ пример на код по-горе.

Сега се върнах към проблема с динамичното създаване на контроли за формуляр по време на изпълнение и отново гледам статиите „Какво се случи за контрол на масиви“.

Създадох класовете и вече мога да поставя контролите върху формата по начина, по който искам да бъдат.

Джон демонстрира как да контролира поставянето на контроли в групово поле, като използва новите класове, които е започнал да използва. Може би Microsoft в крайна сметка е имала право в тяхното "грозно" решение!

instagram story viewer