文档库 最新最全的文档下载
当前位置:文档库 › WPF感悟 TXT 正式版

WPF感悟 TXT 正式版

WPF感悟
感悟1 XAML与C#的语法不对称
XAML的语法与C#的语法并不是完全对称的,最明显的就是在设置Binding的时候。
XAML:

如何看待ItemsSource="{Binding ...}这个attribute?如果认为是
listBox1.ItemsSource = new Binding(...);,那就错了——数据类型都不匹配。实际上,这句XAML对应的C#应该是:
listBox1.SetBinding(ListBox.ItemsSourceProperty, new Binding(...));
为了让Binding更详细,往往把它拎出来写,成为这样:
view plaincopy to clipboardprint?
1. Binding b = new Binding("Path");
2. b.Source = XXXX;
3. listBox1.SetBinding(ListBox.ItemsSourceProperty, b);

===========================================================

补记一点东西:
特别是对于DataContext这个东西——
something.DataContext = aDataSource;

something.SetBinding(DataContextProperty, aBinding);
是完全不一样的(当然不一样!只是工作的时候容易搞混)。前者是设定一个对象的DataContext后,这个DataContext就不变了(是哪个对象就不变了,并不是说这个对象内的内容不变);后者是说这个对象的DataContext借助一个Binding来改变。


感悟2.关于向窗体动态添加控件
这是一个很有意思的话题。
首先,虽然在讲课的时候,我时常会讲到一些关于动态地向窗体中添加控件的例子,但在实际工作中我却很少用用到要这个技术。一般情况下,控件在窗体上是写好的,只是根据需要显示与隐藏。
其次,也是最重要的——我标题用的是“窗体”没有用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方法,把这个变量添加进容器控件就好了。看起来大概是这样:
view plaincopy to clipboardprint?
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编程中也使用它,上面的代码会简化成这样
view plaincopy to clipboardprint?
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摇身一变,肚子里可就“别有洞天”了。




相关文档