WPF感悟(3)——关于向窗体动态添加控件

WPF感悟(3)——关于向窗体动态添加控件

这是一个很有意思的话题。

首先,虽然在讲课的时候,我时常会讲到一些关于动态地向窗体中添加控件的例子,但在实际工作中我却很少用用到要这个技术。一般情况下,控件在窗体上是写好的,只是根据需要显示与隐藏。

其次,也是最重要的——我标题用的是“窗体”没有用Window,这是为什么呢?因为同样看上去是窗体,WinForm编程对应的类是Form,WPF编程对应的类是Window。虽然在运行时(run time)它们都是Windows API用CreateWindowEx函数创建出来的Window Class,但在它们还是.NET类的时候,却有着巨大的区别——特别是体现在内部控件的组织形式上。

WinForm

WinForm窗体里的按钮、文本框等供用户操作的对象称为“控件”(controls)。这些控件可以分为两类,一类是非容器控件,这类控件的内部结构是固定不变的,比如一个Button内部只能是一串文字(还可以设置Button的背景图片),如果你想在Button内显示一个图标后跟上一串文字,要么你写一个自定义控件(派生自Button、再来点儿GDI+的技术)、要么你把文字写在图片上整个作为Button的背景图片;另一类是容器控件,它的内部可以装一些其他控件,这类控件的一个特点就是有一个Controls属性,这是一个ControlCollection。

你可以把Form也看成是一个容器控件。我们说的动态添加控件也就是向容器控件内添加控件了——方法就是先声明一个与控件类型相对应的变量、为它创建一个控件类型的实例、把这个实例初始化好之后再调用Contols.Add方法,把这个变量添加进容器控件就好了。看起来大概是这样:

private void button1_Click(object sender, EventArgs e)
{
	Button button = new Button();
	button.Size = new Size(80, 20);
	button.Text = "OK";
	groupBox1.Controls.Add(button);
}

这里有两点非常重要——

  • WinForm的控件组织是“平面化”的,也就是说,在一个容器控件内,它们处在同一个ControlCollection内、不再有包含关系(除非它是一个容器控件)。如果我们把目光放的宏观一些,那么WinForm窗体在包含容器控件时,可以称之为一棵以容器控件(也只能以容器控件)为结点的、逻辑上的树——但实际工作中我们谁也不会去使用这棵树,因为它没什么用处。后面你会看到,WPF里也有“树”——那是真正的树,WPF几乎一切事件消息路由都依赖于这棵树。
  • 要想向Controls里添加一个初始化完备的控件,你就几乎总要声明一个变量——在WPF里就不用这么做,因为XAML本身的树状结构,再加上新版本.NET支持“对象初始化”语法,使代码变得非常简单。当然,.NET的方便的功能并非WPF所独享的——我们完全可以在WinForm编程中也使用它,上面的代码会简化成这样
private void button1_Click(object sender, EventArgs e)
{
	groupBox1.Controls.Add(new Button { Text = "OK", Size = new Size(80,20) });
}

这种语法叫做“对象初始化器”,这也是我要在下一篇文章——《WPF感悟(4)——对象初始化器传奇》——里将要介绍的内容。

WPF

WPF窗体里的按钮、文本框等UI组件称为“元素”(Element),更确切地说是“UI元素”(与UIElement类对应)。UI元素这个词里隐含了一点,那就是:它一定是“可视”的(Visual),不然怎么让用户去使用呢?

WPF UI元素与WinForm控件最大的不同就是WPF UI元素不再以“容器”和“非容器”作为区分,而是以“内容元素”和“非内容元素”来区分。所谓内容元素,就是说它有一个名为Content的属性——它是Object类型的!要知道,Object类是所有.NET类的父类,这就意味着对于一个内容元素来说,随便你往它里面装什么都可以!装一个UI元素可以、装一组UI元素也可以——把这组元素组合在一个集合里就OK了。

如果内容元素的内容仍然是内容元素呢?一棵真正的、可视化的“树”就形成了。这就是WPF中声明赫赫的Visual Tree,WPF窗体上的事件消息也是沿着这棵可视化树传递的——消息经过每个可视化树上的结点(UIElement)时称为“路由”(Route),这时候我们可以对消息进行处理和控制。这方面的知识我将在《深入浅出WPF》系列文章里仔细介绍。

你可能会问,WPF里有哪些UIElement是Content Element呢?呃……真问住我了。太多了!以至于我只记得几个非Content Element——比如TextBlock、TextBox。在WPF中,非Content Element的表现功能是很弱的,因为它们肚子里的内容太单一了。就拿TextBlock和TextBox来说,它们的内容只能是文本。

Content Element的内容就非常多了!Button就是一个Content元素。在WPF中,Button摇身一变,肚子里可就“别有洞天”了。

……打会儿游戏,晚上接着写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值