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方法,把这个变量添加进容器控件就好了。看起来大概是这样:
  1. private void button1_Click(object sender, EventArgs e)   
  2. {   
  3.     Button button = new Button();   
  4.     button.Size = new Size(80, 20);   
  5.     button.Text = "OK";   
  6.     groupBox1.Controls.Add(button);   
  7. }  
这里有两点非常重要——
  • WinForm的控件组织是“平面化”的,也就是说,在一个容器控件内,它们处在同一个ControlCollection内、不再有包含关系(除非它是一个容器控件)。如果我们把目光放的宏观一些,那么WinForm窗体在包含容器控件时,可以称之为一棵以容器控件(也只能以容器控件)为结点的、逻辑上的树——但实际工作中我们谁也不会去使用这棵树,因为它没什么用处。后面你会看到,WPF里也有“树”——那是真正的树,WPF几乎一切事件消息路由都依赖于这棵树。
  • 要想向Controls里添加一个初始化完备的控件,你就几乎总要声明一个变量——在WPF里就不用这么做,因为XAML本身的树状结构,再加上新版本.NET支持“对象初始化”语法,使代码变得非常简单。当然,.NET的方便的功能并非WPF所独享的——我们完全可以在WinForm编程中也使用它,上面的代码会简化成这样
  1. private void button1_Click(object sender, EventArgs e)   
  2. {   
  3.     groupBox1.Controls.Add(new Button { Text = "OK", Size = new Size(80,20) });   
  4. }  
这种语法叫做“对象初始化器”,这也是我要在下一篇文章——《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摇身一变,肚子里可就“别有洞天”了。
……打会儿游戏,晚上接着写。









本文转自 水之真谛 51CTO博客,原文链接:http://blog.51cto.com/liutiemeng/95270,如需转载请自行联系原作者
目录
相关文章
|
5月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
5月前
|
C# 开发者 Windows
一款基于Fluent设计风格、现代化的WPF UI控件库
一款基于Fluent设计风格、现代化的WPF UI控件库
127 1
|
5月前
|
C# Windows
WPF中如何使用HandyCotrol控件库
WPF中如何使用HandyCotrol控件库
219 1
|
5月前
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
167 0
|
5月前
|
C# UED 定位技术
WPF控件大全:初学者必读,掌握控件使用技巧,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,控件是实现用户界面交互的关键元素。WPF提供了丰富的控件库,包括基础控件(如`Button`、`TextBox`)、布局控件(如`StackPanel`、`Grid`)、数据绑定控件(如`ListBox`、`DataGrid`)等。本文将介绍这些控件的基本分类及使用技巧,并通过示例代码展示如何在项目中应用。合理选择控件并利用布局控件和数据绑定功能,可以提升用户体验和程序性能。
101 0
|
5月前
|
开发框架 前端开发 JavaScript
WPF应用开发之控件动态内容展示
WPF应用开发之控件动态内容展示
|
5月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
|
5月前
|
前端开发 C#
wpfui:一个开源免费具有现代化设计趋势的WPF控件库
wpfui:一个开源免费具有现代化设计趋势的WPF控件库
186 0
|
5月前
|
开发框架 前端开发 C#
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
|
5月前
|
开发框架 前端开发 JavaScript
在WPF应用中使用GongSolutions.WPF.DragDrop实现列表集合控件的拖动处理
在WPF应用中使用GongSolutions.WPF.DragDrop实现列表集合控件的拖动处理