1.0 XAML是啥?
XAML(eXtensible Application Markup Language,可 扩展应用 程序标记语言) 是一种声明性的XML语法 ,像WPF,WF或者Silverlight应用程序通常需要 XAML。Xaml元 素通常映射到,NET类 。 这并不是一个严格的要求 ,但通常都是如此。
1.1 元素 映射到 .net对 象上
一个控制台Demo,需 要引用程序集 PresntationFramework、 PresentatioCore、 WhdowBase和 system.Xaml。
1 using System; 2 using System.Windows; 3 using System.Windows.Controls; 4 5 namespace ConsoleApplication1 6 { 7 class Program 8 { 9 [STAThread] 10 static void Main(string[] args) 11 { 12 var b = new Button { Content="Click Me!" }; 13 var w = new Window { Title="Code Demo",Content=b }; 14 15 var app = new Application(); 16 app.Run(w); 17 } 18 } 19 }
同样的效果由XAML实现,代码如下:
1 <Window x:Class="XMAL.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:XMAL" 7 mc:Ignorable="d" 8 Title="XAML Demo" Height="350" Width="525"> 9 <StackPanel x:Name="stackPanel1"> 10 <Button Content="Click Me!"></Button> 11 <!--<Button Content="Click Me!" Height="200"> 12 <Button.Background> 13 <LinearGradientBrush StartPoint="0.5,0.0" EndPoint="0.5,1.0"> 14 <GradientStop Offset="0" Color="Yellow"></GradientStop> 15 <GradientStop Offset="0.3" Color="Orange"></GradientStop> 16 <GradientStop Offset="0.7" Color="Red"></GradientStop> 17 <GradientStop Offset="1.0" Color="DarkRed"></GradientStop> 18 </LinearGradientBrush> 19 </Button.Background> 20 </Button>--> 21 <!--<Button Name="button1" Content="Button 1" Margin="5" /> 22 <Button x:Name="button2" Margin="5" Click="OnButton2"> 23 <ListBox Name="listBox1"> 24 <Button x:Name="innerButton1" Content="Ihner Button 1" Margin="4" Padding="4" Click="OnInner1" /> 25 <Button x:Name="innerButton2" Content="Inner Button 2" Margin="4" Padding="4" Click="OnInner2" /> 26 </ListBox> 27 </Button>--> 28 <!--<DockPanel> 29 <Button Content="Top" DockPanel.Dock="Top" Background="Yellow"></Button> 30 <Button Content="Top" DockPanel.Dock="Left" Background="Blue"></Button> 31 </DockPanel>--> 32 </StackPanel> 33 </Window>
当然Application的实例也可以在XAML中定义
1 <Application x:Class="XMAL.App" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:XMAL" 5 StartupUri="MainWindow.xaml"> 6 <Application.Resources> 7 </Application.Resources> 8 </Application>
1.2 使用自定义.net类
首先定义一个简单的Person类,包含2个属性,FirstName和LastName;
1 namespace XMAL 2 { 3 class Person 4 { 5 public Person() 6 { 7 FirstName = "one"; 8 LastName = "two"; 9 } 10 11 public string FirstName { get; set; } 12 public string LastName { get; set; } 13 14 public override string ToString() 15 { 16 return string.Format("{0}, {1}", FirstName, LastName); 17 } 18 } 19 }
然后在XAML文件中引入Person类的命名,空间起别名为Local可以看到有很多的.net命名空间可以引用,引入明明空间后,写XAML代码
1 <ListBox> 2 <Local:Person FirstName="12" LastName="34"></Local:Person> 3 </ListBox>
运行程序,ToString()方法就把对象的值显示在列表中。(如果没有TOstring方法则显示的是这个对象)
1.3 把特性用作属性
只要属性的类型可以表示为字符 串,或者可以把字符串转换为特属性型,就可以把属性设置为属性。 下面 的代码段用特性设置 了 Button元 素 的 Content和Backgromd属 性 。 因为 Content属性的类型是 object,所以可 以接受字符串 。 Background属性的类型是 Brush,Brush类型把 BrushConvener类定义为一个转换器类型,这个类用 Typeconvmer特性进行注解 。 BrushConvener使用 一个颜色列表,从 ConverFormString()方法中返回一个SolidColorBrush。<Button Content="Click Me!" Background="Aqua"></Button>
1.4 把特性用作元素
总是可 以使用 元素语法给属性提供值 。 Button类 的 Backgromd属性可以用子元素 Button.Background设 置。 这样,可以把比较复杂的画笔应用于这个属性,
2 依赖属性
2.1 创建依赖属性
WPF使 用 依赖属性完成数据绑定、 动画、 属性变更通知 、 样式化等 。 对于数据绑定,绑 定到.NET属性源上 的 t1I元 素 的属性必须是依赖属性 。依赖属性和.net的属性一样也包含Get和Set访问器,但是依赖属性调用了基类DependencyObject的GetValue()和SetValue()方法,这2个方法都需要一个参数,参数为属性名+Proprty,基类通过Register()方法注册属性,上demo
1 public class DemoDependencyObject : DependencyObject 2 { 3 public static readonly DependencyProperty ValueProperty = 4 DependencyProperty.Register("Value", typeof(int), typeof(DemoDependencyObject)); 5 6 public int Value 7 { 8 get { return (int)GetValue(ValueProperty); } 9 set { SetValue(ValueProperty, value); } 10 } 11 }
DemoDependencyObject
2.2强制值回掉
依赖属性支持强制检查,由此来判断属性的值是否有效,即Register方法的第4个构造,传递一个PropertyMetadatalei类,在CoerValue方法中写入自己的额Code;
1 public static readonly DependencyProperty ValueProperty = 2 DependencyProperty.Register("Value", typeof(int), typeof(DemoDependencyObject),new PropertyMetadata(0,null, CoerValue)); 3 private static object CoerValue(DependencyObject elemnet, object value) 4 { 5 //your code 6 //int newValue = (int)value; 7 //MyDependencyObject control = (MyDependencyObject)elemnet; 8 //newValue = Math.Max(control.Minimun, Math.Min(control.Maximun, newValue)); 9 //return newValue; 10 }
2.3 值变更回掉和事件
为 了 获 得 值 变 更 的信 息 ,依 赖 属 性还支 持值 变 更 回 调 。 在 属 性 值 发 生 变 化 时调 用 的DependencyProperty.Register()方 法中,可 以添加一个 DependencyPropeGhanged事件处理程序 。
1 public static readonly DependencyProperty ValueProperty = 2 DependencyProperty.Register("Value", typeof(int), typeof(MyDependencyObject), new PropertyMetadata(0, OnValueChanged, CoerValue)); 3 4 public static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 5 { 6 int oldValue = (int)args.OldValue; 7 int newValue = (int)args.NewValue; 8 ///your code 9 }
3 附加属性
1 <DockPanel> 2 <Button Content="Top" DockPanel.Dock="Top" Background="Yellow"></Button> 3 <Button Content="Left" DockPanel.Dock="Left" Background="Blue"></Button> 4 </DockPanel>
纳尼,什么鬼,DockPanel.Dock是Button的属性?Button并没有Dock属性,他是通过DockPanel空间附加给Button,为其正起名曰附加属性。附加属性的定义和依赖属性很相似,它是调用RegisterAttached()方法,
1 class MyAttachedPropertyProvide : DependencyObject 2 { 3 public static readonly DependencyProperty myPropertyProperty = 4 DependencyProperty.RegisterAttached("MyProperty", typeof(int), typeof(MyAttachedPropertyProvide)); 5 public int MyProperty 6 { 7 get { return (int)GetValue(myPropertyProperty); } 8 set { SetValue(myPropertyProperty,value); } 9 } 10 public static void SetMyProperty(UIElement element,int value) 11 { 12 element.SetValue(myPropertyProperty,value); 13 } 14 public static int GetMyProperty(UIElement element 15 { 16 return (int)element.GetValue(myPropertyProperty); 17 } 18 }
MyAttachedPropertyProvide
似乎DockPanel.Dock属性只能添加到DockPanel中的控件上,实际上,附加属性可以添加到任何元素上,但是无法识别这个属性值。
1 <Window x:Class="XMAL.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:Local="clr-namespace:XMAL" 7 mc:Ignorable="d" 8 Title="XAML Demo" Height="350" Width="525"> 9 <Grid x:Name="grid"> 10 <Grid.RowDefinitions> 11 <RowDefinition Height="auto"></RowDefinition> 12 <RowDefinition Height="auto"></RowDefinition> 13 <RowDefinition Height="*"></RowDefinition> 14 </Grid.RowDefinitions> 15 <Button Grid.Row="0" x:Name="button1" Content="Button1"></Button> 16 <Button Grid.Row="0" x:Name="button2" Content="Button2" 17 Local:MyAttachedPropertyProvide.MyProperty="5"></Button> 18 <ListBox Grid.Row="2" x:Name="list1"></ListBox> 19 </Grid> 20 </Window>
C#的使用
1 public MainWindow() 2 { 3 InitializeComponent(); 4 5 MyAttachedPropertyProvide.SetMyProperty(button1, 44); 6 7 list1.Items.Add(MyAttachedPropertyProvide.GetMyProperty(button1)); 8 }
4 标记扩展
通过标记扩展 ,可 以扩展 XAML的 元素或特性语法 。 如果 XML特 性包含花括号,就表示这是标记扩展 的一个符号 。 特性的标记扩展常常用 作简写记号,而 不再使用 元素 。如StaticResourcrce
要创 建标记扩展 ,可 以定义一个派生 自基类 MarkupExtension的 类 。 大 多数标记扩展名 都有Extension后缀,有 了 自定义标记扩展后 ,就只需重写ProvideeValue()方 法 ,它 返回扩展的值 .返回的类型用MarkupExtensionReturnType注解。
1 public enum Operation { Add, Subtract, Multiply, Divide } 2 [MarkupExtensionReturnType(typeof(string))] 3 public class CalculatorExtension : MarkupExtension 4 { 5 public CalculatorExtension() { } 6 7 public double X { get; set; } 8 public double Y{ get; set; } 9 public Operation operation { get; set; } 10 public override object ProvideValue(IServiceProvider serviceProvider) 11 { 12 IProvideValueTarget provideValue = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 13 if (provideValue != null) 14 { 15 var host = provideValue.TargetObject as FrameworkElement; 16 var prop = provideValue.TargetObject as DependencyProperty; 17 } 18 double result = 0; 19 switch (operation) 20 { 21 case Operation.Add: 22 result = X + Y; 23 break; 24 case Operation.Subtract: 25 result = X - Y; 26 break; 27 case Operation.Multiply: 28 result = X * Y; 29 break; 30 case Operation.Divide: 31 result = X / Y; 32 break; 33 default: 34 throw new ArgumentException("error"); 35 } 36 return result; 37 } 38 }
CalculatorExtension
1 <Window x:Class="XMAL.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:Local="clr-namespace:XMAL" 7 mc:Ignorable="d" 8 Title="XAML Demo" Height="350" Width="525"> 9 <StackPanel> 10 <TextBlock Text="{Local:Calculator operation=Add,X=3,Y=4}"/> 11 <TextBlock> 12 <TextBlock.Text> 13 <Local:CalculatorExtension> 14 <Local:CalculatorExtension.operation> 15 <Local:Operation>Multiply</Local:Operation> 16 </Local:CalculatorExtension.operation> 17 <Local:CalculatorExtension.X>7</Local:CalculatorExtension.X> 18 <Local:CalculatorExtension.Y>11</Local:CalculatorExtension.Y> 19 </Local:CalculatorExtension> 20 </TextBlock.Text> 21 </TextBlock> 22 </StackPanel> 23 </Window>
5 XAML定义的标记扩展
用 XAML定 义 的其他标记扩展有 TypeExtension(x:Type) ,它 根据字符 串输入返 回类 型 ;NullExtension(x:Null),它 可以用于在 XAML 中把值设置为空;StaticExtension(x:static),它 可调用类的静态成员。
未完待续。。。。。。。