XAML语法入门
XAML发音"zammel",以XML为标准格式。在XAML中您可以使用XML描述类的层次结构,可以使用Visual Studio和Expression等工具可视化编辑。其中命名空间、属性、实例对象、事件等,在XAML中进行了约束制定规则。可在Silverlight、XBAP、WPF Application等平台中使用XAML文件,所以见意您详细阅读本章。
<Canvas图1
xmlns=" http://schemas.microsoft.com/client/2007 "
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml "
Width="1024" Height="768"
x:Name="rootCanvas"
Loaded="canvasLoaded">
一个XAML文件最终描述的是一个类,其中标签名Canvas是XAML文件描述的类继承的控件类名(如果不是默认命名空间,则必须的加上空间的前缀),同时Code中也继承此类。在浏览器中Silverlight作为一个控件的角色加载,所以此处中的Canvas也可以其它的控件比如:Panel,Control基类等。在XBAP中浏览器会把XAML作为页面执行,所以XBAP中的XAML应为Page派生类,在WPF Application中的XAML文件应是Application的派生类。其中属性Width和Height为面板的面积,Loaded为加载事件,其中Window和Height在属性获取时会转换为Int32类型,而Loaded会转换为canvasLoaded的委托。
命名空间
在“图1”的XAML标记中,其中xmlns="http://schemas.microsoft.com/client/2007 "是XAML文件中的默认命名空间,其中http://schemas.microsoft.com/client/2007 代表的是一组.Net类库命名空间,包括:“System.Windows 和 System.Windows.Controls”等基本控件命名空间,是XAML处理器进行制定的,所以也会随版本不同而变化。
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml ",其中xmlns:x中的x可以随意用其它字母代替,实现命字空间的声明。在调用此命名空间的成员时使用x:成员名就可以。成员基本包括:“x:Array、x:Class、x:ClassModifier、x:Code、x:FieldModifier、x:Key、x:Name、x:Null、x:Shared、x:Static、x:Subclass、x:Type、x:TypeArguments、x:Uid、x:XData”,由XAML处理器的版本而升级变化。
映射到自定义类和程序集
语法使用下列可能的命名标记和值:
clr-namespace: 在包含要作为元素公开的公共类型的程序集中声明的公共语言运行库 (CLR) 命名空间。
assembly= 是指包含部分或全部引用的 CLR 命名空间的程序集。该值通常只是程序集的名称,而不是路径。该程序集的路径必须在生成编译的 XAML 的项目文件中以项目引用的形式建立。另外,为了合并版本管理和强名称签名,该值也可以是 AssemblyName 定义的字符串。
请注意,分隔 clr-namespace 标记和其值的字符是冒号 (:),而分隔 assembly 标记和其值的字符是等号 (=)。这两个标记之间使用的字符是分号。例如:
xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary.dll"
映射到当前程序集
如果引用的 clr-namespace 是在引用自定义类的应用程序代码所在的程序集中定义的,则可以省略 assembly。这种情况的等效语法是指定 assembly=,等号后不需要任何字符串标记。
如果自定义类是在同一程序集中定义的,则不能将其用作页的根元素。不需要映射分部类;如果您希望在 XAML 中将自定义类作为元素引用,只需要映射应用程序中页的非分部类。
属性
XAML中的属性和XML中的属性一样,只不过XAML对其读取方式不同!比如Width="2",其中读取时通过TypeConverter转换为Int32类型了。在标记对象名称的后面使用名称="值"的格式,在转换时经过三个步骤如下:
1、如果 XAML 处理器遇到一个大括号,或者遇到一个从 MarkupExtension 派生的对象元素,则将首先计算所引用的标记扩展(而不是将该扩展作为字符串来处理),而且将使用由标记扩展返回的对象。在许多情况下,由标记扩展返回的对象将是对现有对象的引用,或者是一个将计算推迟到运行时的表达式,而不是一个新对象。
2、如果该属性 (Property) 是用指定的 TypeConverter 声明的,或者该属性 (Property) 的值类型是用属性 (Attribute) TypeConverter 声明的,则该属性 (Attribute) 的字符串值将作为转换输入提交到类型转换器,该转换器将返回一个新的对象实例。
3、如果没有 TypeConverter,则将尝试直接转换为属性类型。最后一个级别是直接在基元类型之间转换,或者在枚举中检查名称(这将返回匹配的值)。
在没有找到制定的格式将会异常失败!
枚举属性
声明属性时如果类型为Enum(枚举),在XAML中您只需要输入枚举中的成员名称。XAML会通过Enum.Parse方法获取其真正成员,其中类型为“枚举属性类型”中找到其成员名称。多个值可以使用逗号分割,但如果有此添加TypeConverter类型转换器时,则有可能是加号(+)等等区分。
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
属性元素
由于属性是有多种类型的,可以是String、Int32、自定义类。当一些.Net类中没有TypeConverter转换器时,“属性名=值”方式是表达不了一个类的。也就不可能赋予给属性,所以XAML中提供了元素为属性,格式如下:
<Window图2
xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml "
Title="styles" Height="265" Width="402">
<Window.Resources>
<Style x:Key="btnStyle" TargetType="Button">
<Style.Setters>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Background" Value="AliceBlue"/>
</Style.Setters>
</Style>
</Window.Resources>
<Button Style="{StaticResource btnStyle}" Name="button1">WPF HOME</Button>
</Window>
这段代码实现了Button的样式功能,其中Style对象要添加到Window.Resources里。其中Window.Resources为标记元素,子标记是赋予的值。
附加属性
附加属性是.Net 3.0中WPF控件中的新面象对象架构,两个控件可以互相使用各自的属性值。通常会子控件使用父控件的属性赋值,并且父控件循环子控件,获取自己属性的值并响应的操作,如图3所示。也可以子控件获取父控件的属性,设为子控件的默认值。
声明附加属性:
public static readonly DependencyProperty TopProperty=DependencyProperty.RegisterAttached("PropertyName",ValueType,FromType,defaultPropertyMetadata);
PropertyName:第一个参数为附加属性的名称,用于外部查找使用,XAML中使用此名称。
ValueType:附加属性值的类型
FromType: 类声明所在类的类型引用
defaultPropertyMetadata:在属性初始化时使用的默认值,用于控件在没设置前有默认布局值!
嵌套控件结构 图3
示例代码:
大概Canvas的重写:
public class Canvas:Panel{
public static readonly DependencyProperty TopProperty=DependencyProperty.RegisterAttached("Top",typeof(int),typeof(Canvas),new PropertyMetadata(0));
public static readonly DependencyProperty LeftProperty=DependencyProperty.RegisterAttached("Left",typeof(int),typeof(Canvas),new PropertyMetadata(0));
//...其它属性
[TypeConverter("System.Windows.LengthConverter, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
[AttachedPropertyBrowsableForChildren]
public static double GetTop(UIElement element){
return element.GetValue(TopProperty);
}
public static void SetTop(UIElement element, double length){
element.SetValue(TopProperty,length);
}
//...其它Set和Get方法,以此类推。。。
}
XAML中:
<Window x:Class="XamlPad.Window1"
xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml "
Title="Window1" Height="335" Width="348" Padding="0" Margin="0">
<Canvas Width="338" Height="308" x:Name="Canvas1">
<Button Canvas.Left="30" Canvas.Top="51" Height="69" Name="button1" Width="131">Button</Button>
<Button Canvas.Left="179" Canvas.Top="51" Height="69" Name="button2" Width="131">Button</Button>
<Button Canvas.Left="30" Canvas.Top="134" Height="69" Name="button3" Width="131">Button</Button>
<Button Canvas.Left="179" Canvas.Top="134" Height="69" Name="button4" Width="131">Button</Button>
<Button Canvas.Left="30" Canvas.Top="216" Height="69" Name="button5" Width="131">Button</Button>
<Button Canvas.Left="179" Canvas.Top="216" Height="69" Name="button6" Width="131">Button</Button>
<Label Canvas.Left="91" Canvas.Top="9" Height="32" Name="label1" Width="142">Parent Canvas Control</Label>
</Canvas>
</Window>
集合类型属性元素语法
这里指的集合类包括ICollection,IList,IDictionary等.Net标准集合接口实现的类,并用“元素属性”表达。在“元素属性”中添加类型标记,其XAML处理器会自动创建实例并使用Add方法添加入集合属性中。
<Style x:Key="btnStyle" TargetType="Button">图4
<Style.Setters>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Background" Value="AliceBlue"/>
</Style.Setters>
</Style>
图4中<Style.Setters>为集合属性,两个Setter标记表示Setters中的两个对象!
附加事件
其实附加事件和附加属性是相似的,只不过子控件继承了父控件的事件。WPF一些控件默认也使用了事件冒泡机制,在一个Button中Click事件没有取消向中冒时,会检测父控件是否绑定了ButtonBase.Click的附加事件,如果绑定则执行!一直到最顶层控件。
示例代码:
<Window x:Class="XamlPad.Window1"
xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml "
Title="Window1" Height="282" Width="283" Padding="0" Margin="0">
<Canvas Width="260" Height="246" x:Name="Canvas1" ButtonBase.Click="BTNCLICK">
<Button Canvas.Left="13" Canvas.Top="20" Height="64" Name="button1" Width="220">按扭1</Button>
<Button Canvas.Left="13" Canvas.Top="90" Height="64" Name="button2" Width="220">按扭2</Button>
</Canvas>
</Window>
程序代码:
private void BTNCLICK(object sender, RoutedEventArgs e)
{
MessageBox.Show((e.Source as Button).Content.ToString());
}
标记扩展
在TyperConverter这之前由XAML处理器调用MarkupExtension抽象类实现,可以通过绑定、资源表达式获取对象赋于属性。表达式的语法格式使用两个大括号包括指令,比如{Binding ...}。
<Button Style="{StaticResource MyStyle}">My button</Button>
在这里,StaticResource 用来标识 StaticResourceExtension 类,该类提供标记扩展实现。下一个字符串 MyStyle 用作非默认 StaticResourceExtension 构造函数的输入,在该构造函数中,从扩展字符串提取的参数用来声明所请求的 ResourceKey。MyStyle 应当是定义为资源的 Style 的 x:Key 属性 值。StaticResource 标记扩展用法要求使用该资源,在加载时通过静态资源查找逻辑来提供 Style 属性值。
本文是由灵在微软官方和其它博客的资料整理加上自己的总结!有关详细其它资料,请参见微软官方网址:http://msdn2.microsoft.com/zh-cn/library/ms788723.aspx