WPF(二) XMAL

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars" x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>   </Grid>
</Window>

在Vs中刚刚建立WPF项目后,进入.xaml文件,显示如上图所示类似。使用标签生命一个元素(每个元素对应内存中一个对象)时,需要使用其实标签<tab>和结束标签</tag>,夹在起始标签和终止标签中的XAML代码表示隶属于这个标签的内容。如果没有什么类容隶属于这个标签,可以写为<tag/>。

   为了表示同类标签中的某个标签的与众不同,可以给它的特征(Attribute)赋值。为特征赋值的语法如下:

  • 非空标签:<tag Attribute1=value1 Attribute2=value2>content</tag>
  • 空标签<tag Attribute1=value1 Attribute2=value2/>

    Attribute则是编程语言文法层面的东西。比如有两个同类语法的元素A和B,为了表示A与B不完全相同或者A与B的用法上有些区别,这时候就要针对A和B加一些Attribute。也就是说Attribute只与语言层面上的东西有关,与抽象出来的对象没有什么关系。因为Attribute是为了表示“区分”的。所以它译为“特征”。C#中的Attribute就是这种应用的典型例子,我们可以为一个类添加Attribute,这个类里面有很多Property(属性)。显然,Attribute只用来影响类中程序中的用法,而Property 则对应着抽象对象身上的性状,根本不是一个层面上的东西。(类似同一个标签加上不同的属性`?不知道这样理解对不对)

   因为XAML是用来在UI上绘制控件的,而控件本身就是面向对象的抽象产物,所以XAML标签中的Atrribute有一大部分和它对应他的对象的Property是一一对应的。当然,这还意味着标签中的Atrribute并不对应它所代表对象的Property。

<Window>
    <Grid>
        
    </Grid>
</Window>

  明白了XAML的格式以及Atrribute和Property之间对应的关系,对上面的代码可谓是一目了然。它的总体结构是一个Window标签内包含一个Grid标签(或者说Grid标签是Window标签的内容),所代表的内容是一个Window对象里面包含一个Grid对象。

         XAML是一种声明式语言,当你看见一个标签,就证明你声明了一个对象,对象之间的关系要么是并列,包含全都体现在标签的关系上。

  下面的代码就是<WIndow>标签的Atrribute。

        x:Class="WpfApplication2.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="300" Width="300"

     其中Title、Width、Height一看就知道和Window的Property对象对应的。中间两行(即两个xmlns)实在声明名称空间。最上面一行是在使用名为class的Attribute,这个Attribute来自于X:前缀所对应的名称空间。下面仔细解释 

      前面已经说过,XMAL语言是从XML语言派生而来的。XML有一个功能就是可以在XML文档的标签内使用xmlns特征来定义名称空间(NameSpace),XML也就是XML--NameSpace的缩写。定义名称空间的好处就是,当来源不同的类重名时,可以使用名称空间加以区分。xmlns特征的语法如下:

xmlns[:可选的映射前缀]=“名称空间”

     xmlns后可以跟一个可选的映射前缀,之前用冒号隔开。如果没有写可选映射的前缀,那就意味着所有来自这个名称空间的所有标签都不用加这个前缀,这个没有映射的命名空间称为“默认的命名空间”,默认名称空间只能有一个,而且应该选择其中使用最频繁的名称空间来作为默认命名空间。在上面的例子中,<Window>和<Grid>来自于第二行声明的默认命名空间,而第一样的CLASS特征则来来自于三行的中x:前缀对应的名称空间。这里可以做一个有趣的小实验:如果给第二行声明的名称空间加一个前缀,例如n,那么代码必须要改成一下形式编译才能通过:

<n:Window x:Class="WpfApplication2.Window2"
        xmlns:n="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="300" Width="300">
    <n:Grid>
        
    </n:Grid>
</n:Window>
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon" 
        xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
        xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"

  上面是定义了5个名称空间,其中第一个是默认名称空间

     XAML中引用外来程序集和其中.NET名称空间的语法和C#是不一样的。在C#中,如果想使用System.Windows.Control名称空间内的Button类,需要先把包含System.Windows.Control名称空间的程序集PresentationFramework.dll添加引用到项目中,然后再用C#代码顶部写上一句:using System.Windows.Control;。在XAML中做同样的事情也需要添加对程序集的引用,然后再在根元素的起始标签中写上一句:xmlns:c="clr-namespace:System.Windows.Control;assembly=PresentationFramework"。c是映射的前缀,换成其它字符串也可以。因为button来自前缀为c的命名空间,所以在使用button的时候就要使用<c:Button>....</c:Button>。

    xmlns:c="clr-namespace:System.Windows.Control;assemble=PresentationFramework",这么长的一串字符串看上去的确有点恐怖,但不用担心,VS2008中有自动提示功能。

     在VS自动提示的顶部,你会看到几个像网站地址的几个名称空间,其中就包含例子代码中的那两行。为什么名称空间看上去想一个网站地址呢。其实把它copy到浏览器地址栏尝试跳转也不会打开网页。这里只是XAML解释器的一个硬性编码(hard-coding),只要见到这些固定的字符串,就会把一系列的程序集和程序集中包含的名称空间引入进来。

   默认引入的这两个名称空间格外的重要,它们对应的程序集和.net名称空间如下:

             http://schemas.microsoft.com/winfx/2006/xaml/presentation对应:

  System.Windows;

             System.Windows.Automation;

             System.Windows.Control;

             System.Windows.Control.Primitives;

             System.Windows.Data;

             System.Windows.Document;

             System.Windows.Forms.Intergration;

             System.Windows.Ink;

             System.Windows.Input;

             System.Windows.Media;

             System.Windows.Media.Animation;

             System.Windows.Media.Effects;

             System.Windows.Media.Imaging;

             System.Windows.Media.Media3D;

             System.Windows.Media.TextFormmatting;

             System.Windows.Navigation;

             System.Windows.Shapes;

 也就是说你可以在XAML中可以直接使用这些CLR名称空间下的类型(因为默认XML名称空间前没有前缀)。

   http://schemas.microsoft.com/winfx/2006/xaml则对应一些与XAML语法和编译相关的CLR名称空间, 使用这些名称空间中的类型需要加上前缀x,因为它们被映射到x的XML名称空间中。

    从这两个名称空间的名字和它所对应的.NET程序集上,这个不难看出,第一个空间名称对应的是绘制UI相关的程序集,是表示(Presentation)层面上的东西;第二个名称空间则对应着XAML解析处理相关的程序集,是语言层面上的东西。

            还剩下x:Class="WpfApplication2.Window2"这个Attribute。x前缀说明这个Attribute来着于x映射的名称空间----前面我们解释过,这个名称空间对应XAML解析功能的。x:Class,顾名思义他与类有一些关系,是何种关系呢,让我们做一个有趣的实验:

         首先,x:Class="WpfApplication2.Window2"这个Attribute删掉,再到Windows.xaml.cs文件里,把构造中对InitalizeComponent方法的调用也删掉。编译程序,你会发现,程序依然可以运行,为什么呢?打开App.xaml这个文件,你会发现这样一个Attribute------StartupUri="Window1.xaml",是它告诉编译器把Window1.xaml作为程序启动的主窗体。也就是说,只要Windows1.Xaml能够被解析为一个窗体,程序就能够运行。

        然后只恢复x:Class="WpfApplication2.Window2"这个Attribute(不恢复InitalizeComponent方法的调用)。编译之后仍然可以运行,这是使用IL Disassembler(中间语言凡编译器)打开项目的编译结果,你会发现在由项目编译生成的程序集里面包含一个名为Window2的类,如下图所示

 这说明,XAML这个Attribute的作用是当XAML解析器将它的标签解析成C#类之后,这个类的类名是什么。这里已经触碰到XAML的本质。前面我们已经看到,事例代码的结构就是使用XAML语言直观的告诉我们,当前的窗体是一个<Window>里面嵌入了一个<Grid>。如果是使用C#完成同样的设计呢?显然,我们不可能去更改Window这个类,我们能做的是从Window派生一个类,再为这个类添加一个Grid类型的字段,然后把这个字段初始化的时候赋值给派生类的类容属性。代码看起来大概是这样:

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.Shapes;
 
namespace WpfApplication2
{
    /// <summary>
    /// Window2.xaml 的交互逻辑
    /// </summary>
    public partial class Window2 : Window
    {
        private Grid grid;
        public Window2()
        {
            grid = new Grid();
            this.Content = grid;
        }
    }
}

    最后让让我回到最初的代码。你可能会问:在XAML里面有x:Class="WpfApplication2.Window2",在Windows2.xaml.cs里面也声明了Window2这个类,难道他们不会冲突吗?仔细看看Windows2.xaml.cs中Window2的声明就知道了----在声明的时候使用的是partial关键字,这样,这样由XAML中解析成的类和C#文件里面定义的部分就合二为1了,正是由于这种partial机制,我们可以把逻辑代码留在.cs文件里,用C#语言来实现,而把那些声明及布局UI元素的代码分离出去,实现UI和逻辑分离,并且,用于绘制UI的代码(如声明控件类型的字段,设置它们的外观和布局等)也不必再使用C#语言,使用XAML和XAML编辑工具就可以轻松搞定。       

转载请注明出处:http://blog.csdn.net/fwj380891124

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值