从VB.NET中省略控件数组对那些讲授数组的人来说是一个挑战。
如果引用VB6兼容库,其中的对象的行为与控件数组非常相似。要了解我的意思,只需将VB.NET升级向导与包含控件数组的程序一起使用即可。代码又是丑陋的,但它是有效的。坏消息是,微软不会保证兼容性组件将继续得到支持,你也不应该使用它们。
创建和使用“控件数组”的VB.NET代码要长得多,复杂得多。
根据微软的说法,要做一些甚至接近VB6的事情,需要创建一个“复制控件数组功能的简单组件”
您需要一个新类和一个宿主表单来说明这一点。该类实际上创建和销毁新标签。完整的课程代码如下所示:
公共类LabelArray继承System.Collections.CollectionBase Private ReadOnly HostForm作为uSystem.Windows.Forms.Forms公共函数AddNewLabel()uuSystem.Windows.Forms.Label'创建标签类的新实例。Dim aLabel As New System.Windows.Forms.Label“将标签添加到集合的”内部列表。Me.List.Add(aLabel)‘将标签添加到HostForm字段引用的表单的控件集合’。HostForm.Controls.Add(aLabel)'设置标签对象的初始属性。aLabel.Top=Count*25 aLabel.Width=50 aLabel.Left=140 aLabel.Tag=Me.Count aLabel.Text=“Label”&;Me.Count.ToString返回aLabel End函数Public Sub New(Val host As System.Windows.Forms.Form)HostForm=host Me.AddNewLabel()End Sub默认公共只读属性Val Item(ByVal Index As Integer)As Val Index As System.Windows.Forms.Label Get返回CType(Me.List.Item(Index),System.Windows.Forms.Label)End Get End Get End属性Public Sub Remove()'检查以确保有要移除的标签。如果是我,请计数>;0然后从宿主窗体控件集合中“删除添加到数组中的最后一个标签”注意“访问数组”中默认属性的使用。Remove(Me(Me.Count-1))Me.List.RemoveAt(Me.Count-1)End If End SubEnd类
为了说明如何使用此类代码,您可以创建一个表单来调用它。您必须使用以下表格中显示的代码:
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " ' Also you must add the statement: ' MyControlArray = New LabelArray(Me) ' after the InitializeComponent() call in the ' hidden Region code. ' Declare a new ButtonArray object. Dim MyControlArray As LabelArray Private Sub btnLabelAdd_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnLabelAdd.Click ' Call the AddNewLabel method ' of MyControlArray. MyControlArray.AddNewLabel() ' Change the BackColor property ' of the Button 0. MyControlArray(0).BackColor = _ System.Drawing.Color.Red End Sub Private Sub btnLabelRemove_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnLabelRemove.Click ' Call the Remove method of MyControlArray. MyControlArray.Remove() End Sub End Class首先,这甚至不像我们以前在VB6中做的那样,在设计时完成工作!其次,它们不在数组中,而是在VB.NET集合中-这与数组有很大不同。
VB.NET不支持VB 6“控件数组”的原因是没有“控件”数组(注意引号的变化)。VB6在后台创建一个集合,并使其在开发人员面前显示为数组。但它不是一个数组,除了通过IDE提供的函数外,您对它几乎没有控制权。
另一方面,VB.NET将其称为对象的集合。他们将王国的钥匙交给开发者,通过在公开的环境中创建整个王国。
例如,在VB6中,控件必须具有相同的类型,并且必须具有相同的名称,这就为开发人员提供了一种优势。由于这些只是VB.NET中的对象,因此您可以将它们设置为不同的类型并为它们指定不同的名称,并且仍然可以在同一个对象集合中管理它们。
在本例中,相同的单击事件处理两个按钮和一个复选框,并显示单击的按钮。用VB6在一行代码中实现这一点!
Private Sub MixedControls_Click(_ByValSender作为System.Object,_ByValE作为System.EventArgs)_处理Button1.单击,_Button2.单击,_CheckBox1.单击“下面的语句必须是一条长语句!”这里有四行,以使其足够窄,可以放在网页标签上。Text=Microsoft.VisualBasic.Right(sender.GetType.ToString,Len(sender.GetType.ToString)-(InStr(sender.GetType.ToString,“Forms”)+5)End Sub
子串的计算有点复杂,但这不是我们在这里讨论的。您可以在单击事件中执行任何操作。例如,您可以使用If语句中的控件类型为不同的控件执行不同的操作。
Frank的研究小组提供了一个表单示例,该表单有4个标签和2个按钮。按钮1清除标签,按钮2填充标签。再次阅读Frank的原始问题是一个好主意,注意到他使用的示例是一个循环,用于清除标签组件数组的标题属性。下面是与VB 6代码等效的VB.NET。这段代码符合Frank最初的要求!
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " Dim LabelArray(4) As Label 'declare an array of labels Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load SetControlArray() End Sub Sub SetControlArray() LabelArray(1) = Label1 LabelArray(2) = Label2 LabelArray(3) = Label3 LabelArray(4) = Label4 End Sub Private Sub Button1_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click 'Button 1 Clear Array Dim a As Integer For a = 1 To 4 LabelArray(a).Text = "" Next End Sub Private Sub Button2_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button2.Click 'Button 2 Fill Array Dim a As Integer For a = 1 To 4 LabelArray(a).Text = _ "Control Array " & CStr(a) Next End Sub End Class如果您尝试使用这段代码,您将发现除了设置标签的属性之外,还可以调用方法。那么,为什么我(和微软)在本文的第一部分费尽心思构建“丑陋”的代码呢?
我不同意它实际上是一个经典VB意义上的“控制数组”。VB6控件数组是VB6语法支持的一部分,而不仅仅是一种技术。事实上,描述这个例子的方式可能是它是一个控件数组,而不是一个控件数组。
在第一部分中,我抱怨微软的例子只在运行时工作,而不是在设计时。您可以动态地在表单中添加和删除控件,但整个过程必须在代码中实现。不能像在VB6中那样拖放控件来创建它们。此示例主要在设计时工作,而不是在运行时。不能在运行时动态添加和删除控件。在某种程度上,它与第一部分的例子完全相反。
经典的VB6控件数组示例与VB.NET代码中实现的示例相同。这里是VB 6代码(摘自Mezick&Hillier,Visual Basic 6认证考试指南,第206页-稍作修改,因为本书中的示例导致无法看到的控件):
Dim MyTextBox as VB.TextBox Static intNumber as Integer intNumber = intNumber + 1 Set MyTextBox = _ Me.Controls.Add("VB.TextBox", _ "Text" & intNumber) MyTextBox.Text = MyTextBox.Name MyTextBox.Visible = True MyTextBox.Left = _ (intNumber - 1) * 1200但正如微软(和我)所同意的,VB 6控件数组在VB.NET中是不可能的。因此,您所能做的就是复制功能。我的文章复制了Mezick&Hillier示例中的功能。学习组代码复制了能够设置属性和调用方法的功能。
所以底线是,这实际上取决于你想做什么。VB.NET还没有将整个内容包装成语言的一部分,但最终它要灵活得多。
John写道:我需要控制数组,因为我想在运行时在表单上放置一个简单的数字表。我不想把它们单独放置,我想使用VB.NET。微软为一个简单的问题提供了一个非常详细的解决方案,但这是一个非常大的大锤来敲开一个非常小的螺母。经过一些实验,我终于想出了一个解决办法。我是这样做的。
上面的About Visual Basic示例演示了如何通过创建对象实例、设置属性并将其添加到作为表单对象一部分的控件集合中,在表单上创建文本框。
将txtDataShow设置为新文本框txtDataShow.Height=19txtDataShow.Width=80txtDataShow.Location=New Point(X,Y)Me.Controls.Add(txtDataShow)尽管Microsoft解决方案创建了一个类,但我认为可以将所有这些内容包装到一个子例程中。每次调用此子例程时,都会在表单上创建textbox的新实例。以下是完整的代码:
公共类Form1继承System.Windows.Forms.Form
#区域“Windows窗体设计器生成的代码”
私有子BtnStart\u单击(\uByVal发送方作为System.Object,\uByVal e作为System.EventArgs)\u处理BtnStart。单击
Dim I作为整数Dim sData作为字符串用于I=1到5 sData=CStr(I)调用AddDataShow(sData,I)下一个结束子AddDataShow(Val sText作为字符串,Val I作为整数)
Dim TXTDASSHOW作为新文本框Dim UserLft,UserTop作为整数Dim X,Y作为整数UserLft=20 UserTop=20 TXTDASSHOW.Height=19 TXTDASSHOW.Width=25 TXTDASSHOW.TextAlign=uu2;水平对齐。Center TXTDASSHOW.BorderStyle=2; BORDERNDERSTYLE.FixedSingle TXTDASSHOW=UserLft Y=UserTop+(I-1)*txtdashow.Height txtdashow.Location=新点(X,Y)Me.Controls.Add(txtdashow)End SubEnd类非常好的点,John。这当然比微软的代码简单得多。。。所以我想知道他们为什么坚持这样做?
为了开始我们的调查,让我们尝试更改代码中的一个属性赋值。我们换衣服吧
txtDataShow.Height=19to
txtDataShow.Height=100只是为了确保有明显的差异。
当我们再次运行代码时,我们得到。。。什么。。。同样的事情。没有任何变化。事实上,您可以使用类似MsgBox(txtDataShow.Height)的语句来显示该值,并且无论您为该属性分配了什么,仍然会得到20作为该属性的值。为什么会这样?
答案是,我们不是派生我们自己的类来创建对象,我们只是向另一个类添加东西,所以我们必须遵循另一个类的规则。这些规则声明您不能更改Height属性。(Wellllll…可以。如果将Multiline属性更改为True,则可以更改高度。)
为什么VB.NET会继续执行代码,甚至连一声呜咽都没有说可能出了什么问题,而实际上,它完全无视您的声明,这完全是另一种抱怨。不过,我可能会建议至少在编译时发出警告。(提示!提示!提示!Microsoft正在侦听吗?)
第一部分中的示例继承自另一个类,这使得继承类中的代码可以使用这些属性。在本例中,将Height属性更改为100可以得到预期的结果。(再一次…一个免责声明:创建大型标签组件的新实例时,它会覆盖旧实例。要实际查看新标签组件,必须添加方法调用aLabel.BringToFront()
这个简单的例子表明,尽管我们可以简单地将对象添加到另一个类中(有时这是正确的做法),但对对象的编程控制要求我们在一个类中派生它们,而最有组织的方式(我敢说,“.NET方式”?)是在新的派生类中创建属性和方法来更改内容。约翰起初仍然不相信。他说,他的新方法符合他的目的,尽管不“COO”(正确的面向对象)存在局限性。然而,最近约翰写道,
“…在运行时编写了一组5个文本框之后,我想在程序的后续部分更新数据-但没有任何更改-原始数据仍然存在。
我发现我可以通过编写代码来摆脱这个问题,去掉旧的盒子,然后用新数据重新放回去。一个更好的方法是使用Me.Refresh。但这个问题引起了我的注意,因为我需要提供一种方法来减去文本框并添加它们。”
John的代码使用了一个全局变量来跟踪表单中添加了多少控件,因此方法。。。
私有子表单1_Load(ByVal发送方作为System.Object,ByVal e作为System.EventArgs)uHandles MyBase.Load CntlCnt0=Me.Controls.CountEnd子表单
然后可以删除“最后一个”控件。。。
N=Me.Controls.Count-1Me.Controls.RemoveAt(N)约翰指出,“也许这有点笨拙。”
这是微软跟踪COM中对象的方式,以及上面的“丑陋”示例代码。
现在,我回到了在运行时在窗体上动态创建控件的问题上,并且再次阅读了“控件数组发生了什么”一文。
我已经创建了类,现在可以按照我希望的方式将控件放置到窗体上。
John演示了如何使用他开始使用的新类控制控件在组框中的放置。也许微软在他们“丑陋”的解决方案中是正确的!
...End function语句括起来的过程。函数执行某个任务,然后将控件返回给调用代码。当它传递控件时,它还将值返回给调用代码。 程序员可以在模块、类或结构中创建函数。默认情况下,函数是公共的。因此,可以从应用程序中可...
...。它们包含静态(X)HTML标记。它还包含定义服务器端Web控件和用户控件的标记。这是开发人员放置网页的所有rc内容的地方。 在ASP.netframework2.0中,引入了一种新的代码隐藏模型。这允许静态文本保留在.aspx页上,而动态代码保...
...。它们包含静态(X)HTML标记。它还包含定义服务器端Web控件和用户控件的标记。这是开发人员放置网页的所有rc内容的地方。 在ASP.netframework2.0中,引入了一种新的代码隐藏模型。这允许静态文本保留在.aspx页上,而动态代码保...
...。它们包含静态(X)HTML标记。它还包含定义服务器端Web控件和用户控件的标记。这是开发人员放置网页的所有rc内容的地方。 在ASP.netframework2.0中,引入了一种新的代码隐藏模型。这允许静态文本保留在.aspx页上,而动态代码保...
...一种高级编程语言,用于快速开发基于Windows的程序。VB.NET代表支持Visual Basic网络的技术。它是Microsoft的.NET framework语言之一。这种语言是专门为VB开发人员创建的。它属于在.NET框架上实现的面向对象计算机编程语言的范畴。VB.NET...
...为整数类型,但可以使用DirectCast将表单类型强制转换为控件类型。 让我们检查一下微软的DirectCast示例的性能。使用上面显示的相同代码模板,替换为。。。 c = DirectCast(f, System.Windows.Forms.Control) ... 与CType和TryCast的类似替...
...须是可重用的,并且必须符合为互操作性设置的标准。 控件在Visual Basic中,用于在Visual Basic窗体上创建对象的工具。控件从工具箱中选择,然后使用鼠标指针在窗体上绘制对象。关键是要认识到控件只是用来创建GUI对象的工具...
...的唯一方法,但它有真正的优势。例如,可以在PictureBox控件中包含位图,或使用mciSendString Win32 API。 Microsoft将资源定义为“与应用程序一起逻辑部署的任何不可执行的数据” 管理项目中资源文件的最简单方法是在项目属性中...
...藏在已编译的“p代码”中。您也可以在VB6中开发自定义控件,但这要困难得多,并且需要Microsoft为此提供的特殊实用程序。 在Form Designer.vb文件中,您会发现以下代码已自动添加到正确的位置,以支持复选框组件。(如果您有...
...的唯一方法,但它有真正的优势。例如,可以在PictureBox控件中包含位图,或使用mciSendString Win32 API。“MCI”是一个前缀,通常表示多媒体命令字符串。 在vb6中创建资源文件 在project Explorer窗口中,您可以在VB 6和VB.NET中看到项...