WPF基础知识

本篇介绍WPF基础知识,包括类层次结构、命名空间、类型转换器、逻辑树与可视树等等。

 

1. WPF类层次结构


 

2. XAML命名空间

XAMLXML-Namespace的缩写。
知识点:
  • 冒号后面的映射名可有可无,不加映射名的即为默认命名空间,这种命名空间仅能有一个。系统默认将http://schemas.microsoft.com/winfx/2006/xaml/presentation作为默认命名空间。
  • 命名空间有属性值继承的功能,父级引用的命名空间子级能直接使用。如下:
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <Grid xmlns:s="clr-namespace:System;assembly=mscorlib">  
  2.     <Button>  
  3.         <s:String>Test</s:String>  
  4.     </Button>  
  5. </Grid>  
  • CLR命名空间与URL标识命名空间。
定义一个MyControl自定义控件dllCLR命名空间引用方式为:
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. xmlns:control1="clr-namespace:MyControl;assembly=MyControl"  
AssemblyInfo.cs代码文件中添加URL命名空间关联
[csharp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. [assembly: XmlnsDefinition("http://test/MyControl", "MyControl")]  
URL命名控件引用方式为
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. xmlns:control2="http://test/MyControl"  
注意,假如定义了URL命名空间关联,在智能提示中,CLR命名空间不再显示,不过还是有效的。
添加默认的命名空间前缀:
[csharp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. [assembly: XmlnsPrefix("http://test/MyControl", "control")]  

3.类型转换器

XAML中都是通过字符串来设定值的,类型转换器的作用就是将字符串转化为相应的CLR对象,譬如将White转化为对应的颜色值。
所有的类型转化器都派生自TypeConverter。TypeConverter提供的4个重要的方法是CanConvertTo、CanConvertFrom、ConvertTo(CLR对象->字符串)和ConvertFrom(字符串->CLR对象)。
自定义类型转换器(人员管理,人员隶属于哪个上级人员):
自定义转换器代码:
[csharp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. private void AddControl()  
  2. {  
  3.     Label label = new Label();  
  4.     label.Content = "通过代码添加";  
  5.     mainGird.Children.Add(label);  
  6.     Grid.SetColumn(label, 0);  
  7.     Grid.SetRow(label, 1);  
  8. }  
  9.   
  10. public class StringToHumanTypeConverter : TypeConverter  
  11. {  
  12.     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)  
  13.     {  
  14.         if(value is string)  
  15.         {  
  16.             Human human = new Human();  
  17.             human.Name = (string)value;  
  18.             return human;  
  19.         }  
  20.         return base.ConvertFrom(context, culture, value);  
  21.     }  
  22.   
  23.     public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)  
  24.     {  
  25.         return true;  
  26.         //return base.CanConvertFrom(context, sourceType);  
  27.     }  
  28. }  

资源代码:
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <Window.Resources>  
  2.     <local:Human x:Key="human" Name="child" Parent="parent"/>  
  3. </Window.Resources>  
测试代码:
[csharp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. private void Button_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.     Human human = (Human)this.FindResource("human");  
  4.     MessageBox.Show(string.Format("子级:{0},父级:{1}", human.Name, human.Parent.Name));  
  5. }  

注意点:

假如不重写CanConvertFrom方法,编译运行能成功,但是会提示:“Human” TypeConverter 不支持从字符串进行转换。

4.标记扩展

标记扩展,就像类型转换器一样,可以用于扩展XAML的表达能力。它们都可以在运行时计算字符串特性的值(除了一些内建的、为提高性能而在编译时计算的标记扩展),并生成一个合适的基于字符串的对象。就像类型转换器一样,WPF有好几个内建的标记扩展,你会发现它们都派生自本书最前面的内封中的MarkupExtension。
标记扩展实际上是一种特殊的Attribute=Value语法,特殊之处在于Value字符串由一对花括号及其括起来的内容组成。XMAL编译器对这样的内容进行解析、生成相应的对象。
如下就是标记扩展用法:
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <Button Background="{x:Null}" Content="{Binding XXX}" />  
摆脱花括号,假如输出文本正好包含一对花括号,而又不是扩展标记,怎么输出花括号呢?
可以通过在其之前增加一对空花括号来实现。如下:
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <Button Content="{}{我是花括号!}" />  

5.逻辑树与可视树

在WPF中,用户界面由一个对象树构建而成,这棵树叫作逻辑树。
可视树基本上是逻辑树的扩展,在可视树中,节点都被打散,分放到核心可视组件中。
并非所有的逻辑树节点都会出现在可视树中,只有从System.Windows.Media.Visual或System.Windows.Media.Visual3D派生的元素才会被包含进去。其他元素(和一些简单的字符串内容,如代码清单3-1中的内容)不会包含在内,因为它们自己并没有与生俱来的呈现行为。
相同的逻辑树,不同的主题,相对应的可视树可能就不同。
下面代码打印出程序的逻辑树与可视树:
[csharp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. //打印逻辑树  
  2. private void PrintLogicalTree(int dept, object obj)  
  3. {  
  4.     //前置空格标识深度  
  5.     Debug.WriteLine(new string(' ', dept) + obj);  
  6.   
  7.     if (!(obj is DependencyObject))  
  8.     {  
  9.         return;  
  10.     }  
  11.   
  12.     foreach (object child in LogicalTreeHelper.GetChildren(obj as DependencyObject))  
  13.     {  
  14.         PrintLogicalTree(dept + 1, child);  
  15.     }  
  16. }  
  17.   
  18. //打印可视树  
  19. private void PrintVisualTree(int dept, DependencyObject obj)  
  20. {  
  21.     //前置空格标识深度  
  22.     Debug.WriteLine(new string(' ', dept) + obj);  
  23.   
  24.     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)  
  25.     {  
  26.         PrintVisualTree(dept + 1, VisualTreeHelper.GetChild(obj, i));  
  27.     }  
  28. }  
效果:

逻辑树:
 
 
可视树:
 
 
 
posted @ 2016-09-29 21:26  天涯海角路  阅读(285)  评论(0)    收藏  举报