X名称空间中的Attribute
Attribute和Property是两个层面的东西:
1)Attribute是语言层面的,是给编译器看的。
2)Property是对象层面的,是给编程逻辑用的。
x:Class
这个Attribute的作用是告诉XAML编译器将XAML标签的编译结果与后台中指定的类合并。使用X:Class时必须遵循一下要求:
1)这个Attribute只能用于根节点。
2)使用x:Class的根节点的类型要与x:Class的值所指示的类型保持一致。
3)x:Class的值所指示的类型在声明时必须使用partial关键字。
x:ClassModifier
这个Attribute的作用是告诉XAML编译由标签编译生成的类具有怎么样的访问控制级别。
需注意:
1)标签必须具有x:Class Attribute。
2)x:ClassModifier的值必须与x:Class所指示类的访问控制级别一致。
3)x:ClassModifier的值随后台代码的编译语言不通而有所不同。
x:Name
XAML的标签声明的是对象,一个XAML标签会对应着一个对象,这个对象一般是一个控制类的实例。在.NET平台上,类是应用类型。引用类型的实例在使用时一般是以“引用者——> 实例”的形式成对出现的,而且我们只能通过引用者来访问实例。当一个实例不再被任何引用者所引用时,它就会被当做内存垃圾而销毁。
常见的引用者是引用变量,但这并不是唯一的。
XAML:
<Window x:Class="Chapter4.Page33.xClassModifier.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:ClassModifier="internal"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Margin="5"/>
<Button Content="OK" Margin="5" Click="Button_Click"/>
</StackPanel>
</Window>
后台代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Chapter4.Page33.xClassModifier
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
internal partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = this.Content as StackPanel;
TextBox textBox = stackPanel.Children[0] as TextBox;
if (string.IsNullOrEmpty(textBox.Name))
{
textBox.Text = "No Name";
}
else
{
textBox.Text = textBox.Name;
}
}
}
}
这里点击按钮的结果是“No Name”。
x:Name的作用有两个:
1)告诉XAML编译器,当一个标签带有x:Name时除了为这个标签生成对应实例外还要为这个实例声明一个引用变量,变量名就是x:Name的值。
2)将XAML标签所对应对象的Name属性(如果有)也设为x:Name的值,并把这个值注册到UI树上,以方便查找。
x:Name的功能覆盖了Name属性的功能,所以全部使用x:Name以增强代码的统一性和可读性。
x:FileModifier
x:FileModifier就是用来在XAML里改变引用变量的访问级别。默认的访问级别是internal(即程序集级别)
<TextBox x:Name="textBox1" x:FieldModifier="public" Margin="5"/>
注意因为x:FileModifier是用来改变引用变量访问级别的,所以使用x:FileModifier的前提是这个标签同时也使用x:Name。
x:Key
最自然的检索方式莫过于使用“Key-Value”对的形式了。在XAML文件中,我们可以把很多需要多次使用的内容提取出来放在资源字典(Resource Dictionary)里,需要使用这个资源的时候就用它的Key把它检索出来。
x:Key的作用就是为资源贴上用于检索的索引。在WPF中,几乎每个元素都有自己的Resources属性,这个属性是个“Key-Value”式的集合,只要把元素放进这个集合,这个元素就成为资源字典中的一个条目,当然,为了能够检索到这个条件,就必须为它添加x:Key。资源(Resources)在WPF中非常重要,需要重复使用的XAML内容,如style、各种Template和动画等都需要放在资源里。
现在Windows1的资源字典中添加一个条目,这个条目是一个字符串,我们将在XAML和C#中多次使用这个字符串。
<Window x:Class="Chapter4.Page33.xClassModifier.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys ="clr-namespace:System;assembly=mscorlib"
x:ClassModifier="internal"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<sys:String x:Key="myString">Hello WPF Resource</sys:String>
</Window.Resources>
<StackPanel Background="Gray">
<TextBox Text="{StaticResource ResourceKey=myString}" Margin="5"/>
<TextBox x:Name="textBox1" Margin="5"/>
<Button Content="Show" Click="Button_Click" Margin="5"/>
</StackPanel>
</Window>
资源不但可以在XAML中访问,在C#中也可以访问: as 运算符类似于强制转换操作。 但是,因此,如果转换是不可能的,as 返回 null 而不引发异常。
private void Button_Click(object sender, RoutedEventArgs e)
{
string str = this.FindResource("myString") as string;
this.textBox1.Text = str;
}
调用一个拥有Resource属性的对象的FindResource方法就可以在它的资源字典里检索资源,检索到资源之后再把它恢复成正确的数据类型就可以使用了。
x:Shared
在学习x:Key时我们已经知道,一旦我们把某些对象当做资源放进资源字典后就可以把他们检索出来重复使用。那么,每当它们检索到一个对象时,我们得到的究竟是同一个对象,还是这个对象的多个副本呢?这就要看我们给x:Shared赋什么值了。x:Shared一定要与x:Key配合使用,如果x:Shared的值为true,那么每次检索到这个对象时,我们得到的都是同一个对象,否则如果x:Shared的值为false,每次我们检索到这个对象时,我们得到的是这个对象的一个新副本。XAML编译器会为资源隐藏地添加x:Shared=“true”,也就是默认情况下我们得到的都是同一个对象。
X名称空间中的标记扩展Makeup Extension
1)x:Type
x:Type的值是一个数据类型的名称。我们在XAML中想表达某个数据类型时候就需要使用x:Type标记扩展。比如某个类的一个属性,他的值要求是一种数据类型,当我们在XAML为这个属性赋值时就要使用x:Type。
例子:首先,创建一个Button的派生类,重写Button的OnClick方法,并且增加一个UserWindowType属性:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
namespace Chapter4.Page39
{
public class MyButton:Button
{
public Type UserWindowType { get; set; }
protected override void OnClick()
{
base.OnClick(); //激发Click事件
//Activator.CreateInstance 方法 (Type) 使用指定类型的默认构造函数来
//创建该类型的实例。type类型:System.Type
Window win = Activator.CreateInstance(this.UserWindowType) as Window;
if (win != null)
{
win.ShowDialog();
}
}
}
}
这个类具有一个Type类型的属性,即UserWindowType,需要把一种数据类型当做值赋值给它。同时,这个类还重写了基类的OnClick方法——除了可以像基类那样触发Click事件外,还回使用UserWindow所存储的类型创建一个实例,如果这个实例是Window类(或其派生类)的实例,那么就会把这个窗体显示出来。
然后,在项目里添加了一个名为MyWindow的Window派生类。
<Window x:Class="Chapter4.Page39.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyWindow" Height="300" Width="300">
<StackPanel Background="LightBlue">
<TextBox Margin="5"/>
<TextBox Margin="5"/>
<TextBox Margin="5"/>
<Button Content="OK" Margin="5"/>
</StackPanel>
</Window>
最后,把自定义按钮添加到主窗口的界面上,并把MyWindow作为一种数据类型赋值给MyButton.UserWindowType属性:
<Window x:Class="Chapter4.Page39.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Chapter4.Page39"
Title="MainWindow" Height="350" Width="525">
<Grid>
<!--在这里我们使用我们从button类继承的mybutton类,并且为MyButton类的UserWindowType属性赋值,
由于UserWindowType的类型为Type,所以我们要使用x:Type来获取MyWindow类的类型值,
而且由于我们在MyButton类中重写onClick,所以这里也不用写OnClick也会触发该方法-->
<local:MyButton Content="Show" UserWindowType="{x:Type TypeName=local:MyWindow}" Margin="5"/>
</Grid>
</Window>
因为MyButton和MyWindow这两个自定义类都包含在当前项目的名称空间里,所以当前项目的名称空间引用进来并用local前缀映射。在使用MyButton和MyWindow时也要为他们加上local前缀。
回顾一下标记扩展的语法,因为TypeExtension类的构造器可以接受数据类型名作为参数,所以我们完全可以这样写:
<local:MyButton Content="Show" UserWindowType="{x:Type local:MyWindow}" Margin="5"/>
x:Null
有时候我们需要显示地对一个属性赋空值,在XAML里要用来表示控制的就是x:Null。
大多数时候我们不用显示的为一个属性赋空值,但如果一个属性具有默认值而我们又不需要这个默认值时就需要显示地设置null值了。例如在WPF中,Style的作用是按照一定的审美规格设置控件的各个属性,程序员可以通过控件更换Style来产生各种风格迥异的效果。程序员可以逐个为控件设置Style,也可以为一个Style指定目标控制类型,一旦指定了目标类型那么这类控件的实例都使用这个Style,除非显示地将某个实例的Style属性设置为x:Null:
<Window x:Class="Chapter4.Page41.xNull.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="60"/>
<Setter Property="Height" Value="36"/>
<Setter Property="Margin" Value="5"/>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="OK"/>
<Button Content="OK"/>
<Button Content="OK"/>
<Button Content="OK" Style="{x:Null}"/>
</StackPanel>
</Window>
运行结果:
x:Array
x:Array的作用就是通过它的Items属性向使用者暴露一个类型已知的ArrayList实例,ArrayList内成员的类型由x:Array的Type指明。下面这个例子是把一个x:Array当做数据源向一个ListBox提供数据:
<Window x:Class="Chapter4.Page42.xArray.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Margin="5">
<ListBox.ItemsSource>
<x:Array Type="sys:String">
<sys:String>Tim</sys:String>
<sys:String>Tom</sys:String>
</x:Array>
</ListBox.ItemsSource>
</ListBox>
</Grid>
</Window>
x:Static
<Window x:Class="Chapter4.Page45.xStatic.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Chapter4.Page45.xStatic"
Title="{x:Static Member=local:MainWindow.WindowTitle}" Height="350" Width="525">
<Grid>
<TextBox Text="{x:Static local:MainWindow.ShowText}"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Chapter4.Page45.xStatic
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public static string WindowTitle = "山高月亮小";
public static string ShowText
{
get { return "水落石出"; }
}
}
}
注意:如果一个程序需要国际化支持,一般会把需要显示的字符串保存在一个资源类的static属性中,所以支持国际化的程序UI中对x:Static的使用非常频繁。