XAML 是一种基于 XML 语法的用来创建 .NET 对象树的语言。从严格意义上来讲, XAML 与 WPF 是相互独立的。 XAML 更多的算是一种技术,并不是专门供 WPF 使用的。比如 WWF(Windows Workflow Foundation) 就能够用 XAML 表示工作流。 XAML 本质上只是一种用于构建 .NET 对象树的语言,与 WPF 框架没有特殊的关联。下面了解一下 XAML 编译器的工作原理。
命名空间
XAML 使用 XML 命名空间来表示 .NET 命名空间,但是他们之间并不是一对一的通信。一个 XML 命名空间可以包含若干个 .NET 命名空间。有两种方式实现:
第一种是将 XmlnsDefinitionAttribute 应用于那些将要包含在 XAML 中进行访问的类型。 [assembly:XmlnsDefinition(“http://...”,”mynamespace”)] 。
第二种是通过查找命名空间中的类型的方式: xmlns:local="clr-namespace: Samples;assembly=" 。如果 ”clr-namespace:” 后面没有分号,那么它之后的都当做 namespace 来解析,而该命名空间一定在当前程序集中;否则, assembly 后面跟的就是程序集信息。
生成类
x:Class="OpenXMLWriter.Window1"
子元素
XAML 编译器会将子元素加到他的 Child 、 Children 或 Content 属性中,这要根据具体的控件而定。
属性
由于 XAML 中只能够表示文本属性,更准确的说是 String 属性,因此在表示其他类型的属性,如 int 型时,就需要一种类型转换器。对于内置的元素控件系统已经自带了 TypeConverter 。
实例:(这里用到了属性元素语法,即 Parent.PropertyName )
< Button VerticalAlignment ="Center" HorizontalAlignment ="Center">
< Button.Background >
< LinearGradientBrush StartPoint ="0,0" EndPoint ="0,1">
< LinearGradientBrush.GradientStops >
< GradientStop Offset ="0" Color ="#800"/>
< GradientStop Offset ="0.35" Color ="Red"/>
</ LinearGradientBrush.GradientStops >
</ LinearGradientBrush >
</ Button.Background >
</ Button >
等价于:
Button b = new Button ();
b.VerticalAlignment = VerticalAlignment .Center;
b.HorizontalAlignment = HorizontalAlignment .Center;
LinearGradientBrush brush = new LinearGradientBrush ();
brush.StartPoint = new Point (0, 0);
brush.EndPoint = new Point (0, 1);
GradientStop gs = new GradientStop ();
gs.Offset = 0;
gs.Color = Color .FromRgb(0x80, 0, 0);
brush.GradientStops.Add(gs);
gs = new GradientStop ();
gs.Offset = 0.35;
gs.Color = Colors .Red;
brush.GradientStops.Add(gs);
b.Background = brush;
XAML 还支持附加属性。例如:
< Button my : Foo.Bar ="Blue" Name ="btn"/>
然后在 Foo 类中自定义了一个附加属性:
public void SetBar(DependencyObject target, Brush b){………….}
最后等价于: Foo.SetBar(btn, Brushes.Blue);
扩展标记 (Markup extensions)
扩展标记类派生自 System.Windows.Markup.MarkupExtention ,他的使用,使属性的值更加灵活,在运行时决定其值。
public abstract class MarkupExtension
{
protected MarkupExtension() { }
public abstract object ProvideValue(IServiceProvider serviceProvider);
}
XAML 通过两种方式将数据传递给扩展标记:
第一种是构造函数。 < Style TargetType ="{ x : Type Button }"></ Style > 编译时, TypeExtension te = new TypeExtension ("Button" );
第二种是设置属性,通过 PropertyName=Value 的方式。
< TextBlock Text ="{ Binding Path =p, Mode =OneTime, Source ={ StaticResource sn }}"/>
编译后,会生产如下的代码:
Binding bi = new Binding ();
bi.Path = new PropertyPath ("p" );
bi.Mode = BindingMode .OneTime;
bi.Source = FindResource("sn" );
WPF 提供了许多内置的扩展标记,其中以 x: 为前缀的位于 XAML 的 XML 命名空间中,其他的位于 WPF 的命名空间中。
类型 | 说明 |
x:NullExtension | 用来表示空值,在编译时进行求值。 < Button Background ="{ x : Null }"/> 表示将颜色属性设置为 null |
x:TypeExtension | 获得对象的类型,在编译时进行求值。 < Style TargetType ="{ x : Type Button }"></ Style > |
x:ArrayExtension | 创建一个数组。这个并不是很常使用,由于一个组可以包含多个选项,因此该标记可以有子元素。基于这个原因,他是单独作为一个标记。 < x : ArrayExtension Type ="{ x : Type Brush }" x : Key ="brushes"></ x : ArrayExtension > |
x:StaticExtension | 获得静态属性的值。将目标属性设置成指定静态属性或字段的值,参数形式通常为: Class.Member < TextBlock Background ="{ x : Static Class .Member}" / > |
StaticResourceExtension | 执行一次资源搜索。等价于使用了 FindResource 方法,通过名称返回指定资源的值。 < TextBlock Background ="{ StaticResource key }" Name ="myText"/> |
DynamicResourceExtension | 创建资源绑定。他将属性值与指定的资源关联起来,会跟着资源的改变而改变。 |
ComponentResourceKey | 为跨组件系统资源的引用创建一个资源关键字。 |
Binding | 创建一个数据绑定 |
RelativeSource | 创建一个 RelativeSource 用于数据绑定。 |
TemplateBinding | 用于连接控件模板中的属性和模板化控件中的属性。 |