x名称空间详解

X名称空间里都有什么

  x名称空间映射的是:“http://schemas.microsoft.com/winfx/2006/xaml”,它包含的类均与解析XAML语言有关,可称之为"XAML名称空间"。在解析和编译XAML语言的过程中,我们经常需要告诉编译器一些重要的信息,比如XAML代码的编译结果应该与哪个C#代码的编译结果合并、使用XAML声明的元素是public还是private访问级别等等。这些让程序员能够与XAML编译器沟通的工具就存放在x名称空间里。
  x名称空间包含的工具可以分为Attribute、标记扩展、XAML指令元素三类,下面分别说说他们的功能。

一、x名称空间的Attribute

  Attribute和Property是两个层面的东西,Attribute是语言层面的东西、是给编译器看的,Property是面向对象层面的东西、是给编程逻辑用的,而且一个XAML标签的Attribute里大部分都对应着对象的Property。在使用XAML编程的时候,如果想给它加上一些特殊的标记从而影响XAML编译器对它的解析,这时候需要额外为它添加一些Attribute。比如你想告诉XAML编译器将编译结果与哪个C#编译的类合并,这时候就必须为这个标签添加x:class="目标类名"这样一个Attribute告诉XAML编译器。x:class这个Attribute并不是对象的成员,而是把它从x名称空间里拿出来硬贴上去的。
  下面为一些常用的Attribute。

1.x:Class

  这个Attribute的作用是告诉XAML编译器将XAML标签的编译结果与后台代码中指定的类合并。在使用x:class时必须遵循以下要求:

  • 这个Attribute只能用于根节点。
  • 使用x:Class的根节点的类型要与x:Class的值所指示的类型保持一致。
  • x:Class的值所指示的类型在声明时必须使用partial关键字。

2.x:ClassModifier

  这个Attribute 的作用是告诉XAML编译由标签编译生成的类具有怎样的访问控制级别。使用这个Attribute需要注意:

  • 标签必须具有x:Class Attribute。
  • x:ClassModifier的值必须与x:Class所指示类的访问控制级别一致。
  • x:ClassModifier的值随后台代码的编译语言不同而有所不同,参见TypeAttributes枚举类型。

3.x:Name

  XAML是一种声明式语言。XAML标签声明的是对象,一个XAML标签会对应着一个对象,这个对象一般是一个控件类的实例。在.NET平台上,类是引用类型。引用类型的实例在使用时一般是以“引用者→实例”的形式成对出现的,而且只能通过引用者来访问实例。当一个实例不再被任何引用者所引用。它就会被当做内存垃圾销毁。相当于C#中只new了一个对象,而没有为其添加引用变量。
  XAML这种对象声明语言只负责声明对象二部负责为这些对象声明引用变量。如果我们需要为对象准备一个引用变量以便在C#代码中直接访问就必须显式地告诉XAML编译器——为这个对象声明引用变量,这时x:Name就派上了用处。
x:Name的作用有两个:

  • 告诉XAML编译器,当一个标签带有x:Name时除了为这个标签生成对应实例外还要为这个实例声明一个应用变量,变量名就是x:Name的值。
  • 将XAML标签所对应对象的Name属性(如果有)也设为x:Name的值,并把这个值注册在UI树上,以方便查找。

为TextBox标签添加x:name

    <Grid>
        <TextBox x:Name="textBox" Margin="50"/>
        <Button x:Name="button1" Margin="50" Click="Button3_Click"/>
    </Grid>

在C#中可以通过引用变量直接访问实例。

        private void Button3_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(textBox.Name))
            {
                textBox.Text = "NO Name";
            }
            else
            {
                textBox.Text = textBox.Name;
            }
        }

Name和x:Name的区别:
  Name属性定义在FrameworkElement类中,这个类是WPF控件的基类,所有的WPF控件都具有Name这个属性。当一个元素具有Name属性时,使用Name和x:Name的效果是一样的。但二者不能出现在同一元素中。对于没有Name属性的元素,为了在XAML声明时也创建引用变量以便在C#代码中访问,就只能使用x:Name了。因为x:Name的功能涵盖了Name属性的功能,所以全部使用x:Name以增强代码的统一性和可读性。

4.x:FieldModifier

  XAML的引用变量都是类的字段,默认情况下这些字段的访问级别被设置成了internal。在编程中,有时候需要从一个程序集访问另一个程序集的窗体元素,这时候就需要吧访问级别改为Public。x:FieldModifier就是用来在XAML中改变引用变量的访问级别的。

    <StackPanel>
        <TextBox x:Name="textbox1" x:FieldModifier="public" Margin="5"/>
        <TextBox x:Name="textbox2" x:FieldModifier="public" Margin="5"/>
        <TextBox x:Name="textbox3" Margin="5"/>
    </StackPanel>

使用x:FieldModifier的前提是标签同时使用了x:Name。

5.x:Key

  在XAML中可以把很多需要多次使用的内容提取出来放在资源字典(Resource Dictionary)里,需要使用这个资源的时候就把他的Key检索出来。x:Key就是为资源贴上用于检索的索引。

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="130" Width="200">
    <Window.Resources>
        <sys:String x:Key="myString">Hello WPF Resource!</sys:String>
    </Window.Resources>
    <StackPanel>
        <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#中也能访问。

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string str = (string)FindResource("myString");
            textbox1.Text = str;
        }

在这里插入图片描述

6.x:Shared

  x:Shared要与x:Key配合使用,如果x:Shared=“true”,那么每次检索到这个对象的时候,得到都是同一个对象。如果x:Shared=“false”,每次检索到这个对象时,得到的都是这个对象的一个新副本。XAML会为资源隐藏的添加x:Shared="true"

二、x名称空间中的标记扩展

  标记扩展实际上就是一些MarkupExtension类的直接或间接派生类。x名称空间中就包含了一些这样的类。

1.x:Type

  x:Type的值是一个数据类型的名称,即数据类型(类)本身。当在XAML中想表达某个数据类型时就需要使用x:Type标记扩展。比如某个类的一个属性。它的值要求是一种数据类型,在XAML为这个属性赋值时就要使用x:Type。
首先创建一个Button的派生类

    class MyButton : Button
    {
        public Type UserWindowType { get; set; }
        protected override void OnClick()
        {
            base.OnClick();//激发Click事件
            Window win = Activator.CreateInstance(UserWindowType) as Window;
            if (win != null)
            {
                win.ShowDialog();
            }
        }
    }

这个类具有一个Type类型的属性,即UserWindowType,需要把一种数据类型当做值赋给它。同时这个类还重写了基类的OnClick()方法——除了可以像基类那样触发Click事件外,还会使用UserWindowType所存储的类型创建一个实例,如果这个实例是Window类(或其他派生类)的实例,那么就把这个窗体显示出来。
然后在项目里添加一个名为Window1的Window派生类。它的UI包含三个TextBox和一个Button。

<Window x:Class="MyWindow.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="Window1" Height="150" Width="200">
    <StackPanel Background="LightBlue">
        <TextBox Margin="5"/>
        <TextBox Margin="5"/>
        <TextBox Margin="5"/>
        <Button Content="OK" Margin="5"/>
    </StackPanel>
</Window>

最后,把自定义按钮添加到主窗口的界面,并把Window1作为一种数据类型赋值给MyButton.UserWindowType属性:

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <StackPanel>
        <local:MyButton Content="Show" UserWindowType="{x:Type TypeName=local:Window1}" Margin="5"/>
    </StackPanel>
</Window>

编译并运行程序,单击主窗体上的按钮,自定义窗体就会显示出来。
在这里插入图片描述

2.x:Null

  为属性显式的赋一个空值。在XAML中用来表示空值的是x:Null。如果一个属性具有默认值而我们不需要这个默认值时就需要显式地设置null值

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Window.Resources>
        <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
            <Setter Property="Width" Value="60"/>
            <Setter Property="Height" Value="36"/>
            <Setter Property="Margin" Value="5"/>
            <Setter Property="Background" Value="Red"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Content="OK"/>
        <Button Content="OK"/>
        <Button Content="OK"/>
        <Button Content="OK" Style="{x:Null}"/>
    </StackPanel>
</Window>

上面例子把一个Style放在了Window的资源里并把它的x:Key和TargetType都设置成了Button类型,这样,UI上的所有Button控件都会默认地被套用这个Style——除了最后一个Button——因为它显式地把Style设置为了x:Null。
在这里插入图片描述

3.x:Array

  如果想在XAML文档里声明一个包含数据的x:Array实例,必须使用标签式声明。x:Array的作用就是通过它的Items属性向使用者暴露一个类型已知的ArrayList实例,ArrayList内成员的类型由x:Array的Type指明。下面这个例子是把一个x:Array当做数据源向一个ListBox提供数据。在WPF中把包含数据的对象称为数据源(Data Source)。如果想把一个x:Array实例作为数据源提供给一个ListBox的话,代码是这样:

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid Background="LightBlue">
        <ListBox ItemsSource="{x:Array Type=sys:String}" Margin="50"/>
    </Grid>
</Window>

此时作为数据源的x:Array实例是没有数据可提供的,所以需要为x:Array实例添加一些数据。向ArrayExtension中添加数据需要调用它的AddChild方法,而在XAML中无法编写逻辑代码。ArrayExtension的Items属性是只读的。因此只能改用标签声明语法。

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid Background="LightBlue">
        <ListBox Margin="50">
            <ListBox.ItemsSource>
                <x:Array Type="sys:String">
                    <sys:String>Tom</sys:String>
                    <sys:String>Tim</sys:String>
                    <sys:String>Jack</sys:String>
                </x:Array>
            </ListBox.ItemsSource>
        </ListBox>
    </Grid>
</Window>

这样在解析<x:Array>标签的时候编译器会生成调用AddChild方法的代码把<x:Array>标签的子元素逐个添加到x:Array实例的Items里。
在这里插入图片描述

4.x:Static

  x:Static的功能是在XAML文档中使用数据类型的static成员。因为XAML不能编写逻辑代码,所以使用x:Static访问的static成员一定是数据类型的属性或字段。
首先,为MainWindow添加两个Static成员,一个是字段,一个是属性。

   public partial class MainWindow : Window
    {
        public static string WindowTitle = "标题";
        public static string ShowText { get { return "内容"; } }
        public MainWindow()
        {
            InitializeComponent();        
        }
    }

然后在XAML中使用x:Static来访问这两个成员。

<Window x:Class="MyWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:MyWindow"
        mc:Ignorable="d"
        Title="{x:Static local:MainWindow.WindowTitle}" Height="120" Width="300">
    <StackPanel>
        <TextBlock FontSize="32" Text="{x:Static local:MainWindow.ShowText}"/>
    </StackPanel>
</Window>

在这里插入图片描述

三、XAML指令元素

XAML指令元素只有两个:x:Code和x:XData

1.x:Code

  它的作用是可以包含一些本应放置在后置代码中的C#代码。由于不好维护调试基本不使用。

2.x:XData

  x:XData标签是一个专用标签,WPF中把包含数据的对象称为数据源,用于把数据源中的数据提供给数据使用者的对象被称为数据提供者(Data Provider)。WPF类库中包含多种数据提供者,其中有一个类叫做XmlDataProvider,专门用于提供XAML化的数据,如果想在XAML中声明一个带有数据的XmlDataProvider实例,那么XmlDataProvider实例的数据就要放在x:XData标签的内容里。示例如下:

    <Window.Resources>
        <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
            <x:XData>
                <Supermarket xmlns="">
                    <Fruits>
                        <Fruit Name="Peach"/>
                        <Fruit Name="Banana"/>
                        <Fruit Name="Orange"/>
                    </Fruits>
                    <Drinks>
                        <Drink Name="Coca Cola"/>
                        <Drink Name="PEPSI Cola"/>
                    </Drinks>
                </Supermarket>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页