• 关于 WP 开发中.xaml 与.xaml.cs 的关系


    今天我们先来看一下在WP8.1开发中最长见到的几个文件之间的关系。比较论证,在看这个问题之前我们简单看看.NET平台其他两个不同的框架:

    Windows Forms

    先看看Window Forms中的情况,下图为在VS中创建的默认Windows Forms项目结构:

     

    分别回顾一下每个文件以及它们之间的关系:

    ┣━ Properties------------------------------------------- 项目属性文件夹

    ┣━━━━━ AssemblyInfo.cs----------------------------------- 程序集信息声明

    ┣━ App.config------------------------------------------- 应用程序配置文件

    ┣━ Form1.cs--------------------------------------------- 窗体Form1 类文件

    ┣━━━━━ Form1.Designer.cs--------------------------------- 窗体Form1设计 类文件

    ┗━ Program.cs------------------------------------------- 程序入口类文件

    这里我们主要关心的就是Form1.csForm1.Designer.csProgram.cs三个文件,下面我用Visio图表示一下执行流程

    也就是说,Form1.csForm1.Designer.cs最终在编译阶段形成了一个类型,所有的控件的定义和初始化(大多是由于开发者的拖拽和属性编辑操作产生)全部在Form1.Designer.cs这个部分类中完成,代码我就不用贴出来了。我们在开发的时候只需要关心如何在Form1.cs文件中操作部分类中定义的控件成员和编写一些逻辑代码,从而减少开发者的编码量。

    说白了,也就是大家常说的前台UIForm1.Designer.cs)和后台代码(Form1.cs)是部分类的关系,通过partial关键字实现。

    Web Forms

    再来看看Web Form中又是怎样的一种形式:

    这里我们主要是看看WebForm1.aspxWebForm1.aspx.csWebForm1.aspx.designer.cs这三个文件的关系:

    我们都应该知道WebForm1.aspx文件最终也是编译成为一个类存放于一个临时的程序集,对于这个类型来讲,它派生自WebForm1.aspx.cs文件中定义的类,也就是说前台UIWebForm1.aspx)是后台代码(WebForm1.aspx.cs)的子类。那么WebForm1.aspx.designer.cs又是个啥?这里就和WinForms一样了,它和WebForm1.aspx.cs最终也是编译成为一个类型,在WebForm1.aspx.designer.cs也都是定义了一些控件,这也是当年号称很厉害的CodeBehind,目的是将表现和逻辑隔离,当然我们这里不需要评价CodeBehind,本身也不在今天讨论的范畴之中。

    Window Phone / WPF

    最后来看看WP中怎么设计的:

     

    以上是Visual Studio 2013 Update 4中创建的空白Windows Phone 8.1应用,其中有一个MainPage.xamlMainPage.xaml.cs文件,那它两又是什么关系呢?难道是和Windows Forms又或是Web Forms一样吗?

    答案自然是否定的,首先XAML文件中写的XAML代码实际上就是XML语法,官方的说法:它是一个声明对象的语言,为我们创建对象提供便捷的一种方式。与HTML类似,特点是用来描述用户接口UI)内容

    通常我们把与xaml文件关联的xaml.cs文件叫作代码隐藏文件。如果你引用xaml中的任何一个事件处理程序(通过事件特性,如Button的Click事件),这里就是我们定义这些事件处理程序的地方。

    我们先看看后台代码

     1 namespace Demo1
     2 {
     3     /// <summary>
     4     /// 可用于自身或导航至 Frame 内部的空白页。
     5     /// </summary>
     6     public sealed partial class MainPage : Page
     7     {
     8         public MainPage()
     9         {
    10             this.InitializeComponent();
    11 
    12             this.NavigationCacheMode = NavigationCacheMode.Required;
    13         }
    14 
    15         /// <summary>
    16         /// 在此页将要在 Frame 中显示时进行调用。
    17         /// </summary>
    18         /// <param name="e">描述如何访问此页的事件数据。
    19         /// 此参数通常用于配置页。</param>
    20         protected override void OnNavigatedTo(NavigationEventArgs e)
    21         {
    22             // TODO: 准备此处显示的页面。
    23 
    24             // TODO: 如果您的应用程序包含多个页面,请确保
    25             // 通过注册以下事件来处理硬件“后退”按钮:
    26             // Windows.Phone.UI.Input.HardwareButtons.BackPressed 事件。
    27             // 如果使用由某些模板提供的 NavigationHelper,
    28             // 则系统会为您处理该事件。
    29         }
    30 
    31         private void btnHello_Click(object sender, RoutedEventArgs e)
    32         {
    33             txtResult.Text = "Hello World";
    34             var temp = (TextBlock)base.FindName("txtResult");
    35             temp.Text = "Hello World2";
    36         }
    37     }
    38 }
    MainPage.cs

    对于后台代码文件中定义的类同样也有个partial ,貌似跟Windows Phone有点类似。但是我们找了找整个解决方案并没有发现有一个与之对应的部分类,但是根据CodeLens的提示,我们能发现确实有部分类的存在而且是两个类文件MainPage.g.csMainPage.g.i.cs

    分别双击打开这个类文件

    MainPage.g.cs

     1 namespace Demo1
     2 {
     3     partial class MainPage : global::Windows.UI.Xaml.Controls.Page, global::Windows.UI.Xaml.Markup.IComponentConnector
     4     {
     5         [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
     6         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     7 
     8         public void Connect(int connectionId, object target)
     9         {
    10             switch(connectionId)
    11             {
    12             case 1:
    13                 #line 22 "....MainPage.xaml"
    14                 ((global::Windows.UI.Xaml.Controls.Primitives.ButtonBase)(target)).Click += this.btnHello_Click;
    15                  #line default
    16                  #line hidden
    17                 break;
    18             }
    19             this._contentLoaded = true;
    20         }
    21     }
    22 }
    MainPage.g.cs

    MainPage.g.i.cs

     1 namespace Demo1
     2 {
     3     partial class MainPage : global::Windows.UI.Xaml.Controls.Page
     4     {
     5         [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
     6         private global::Windows.UI.Xaml.Controls.Button btnHello;
     7         [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
     8         private global::Windows.UI.Xaml.Controls.TextBlock txtResult;
     9         [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
    10         private bool _contentLoaded;
    11  
    12         [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
    13         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    14         public void InitializeComponent()
    15         {
    16             if (_contentLoaded)
    17                 return;
    18  
    19             _contentLoaded = true;
    20             global::Windows.UI.Xaml.Application.LoadComponent(this, new global::System.Uri("ms-appx:///MainPage.xaml"), global::Windows.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Application);
    21  
    22             btnHello = (global::Windows.UI.Xaml.Controls.Button)this.FindName("btnHello");
    23             txtResult = (global::Windows.UI.Xaml.Controls.TextBlock)this.FindName("txtResult");
    24         }
    25     }
    26 }
    MainPage.g.i.cs

    从这两个文件中我们可以看到,MainPage类在这里还定义了一些控件和相关的方法,并且InitializeComponent()方法里面加载和解析了MainPage.xaml文件MainPage.cs文件里面的MainPage()方面里面调用的InitializeComponent()方法就是在MainPage.g.cs文件里面定义的。在xaml页面中声明的控件,通常会在.g.cs中生成对应控件的内部字段。实际上这取决于控件是否有x:Name属性,只要有这个属性,都会自动调用FindName方法,用于把字段和页面控件关联。没有x:Name属性,则没有字段,这种关联会有一定的性能浪费,因为是在应用载入控件的时候,通过LoadComponents方法关联的,而xaml也是在这个时候动态解析的。

     

    由此我们就会萌生一个动态加载XAML的想法:

    我在页面上添加一个按钮,当按钮点击时执行如下代码:

     1 int top = 100;
     2 private void btnHello_Click(object sender, RoutedEventArgs e)
     3 {
     4     string temp = "<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  " +
     5         " Content="这是动态加载的按钮"/>";
     6     Button btnTemp = (Button)XamlReader.Load(temp);
     7     // 设置水平对其方式
     8     btnTemp.HorizontalAlignment = HorizontalAlignment.Center;
     9     // 让Margin每次都变一下
    10     btnTemp.Margin = new Thickness(0, top-=100, 0, 0);
    11     // 动态设置点击事件
    12     btnTemp.Click += btnHello_Click;
    13     grid.Children.Add(btnTemp);
    14 }
    动态加载按钮XAML

    效果如下图所示:

    通过C#创建按钮的形式:

     1 /// <summary>
     2 /// 在此页将要在 Frame 中显示时进行调用。
     3 /// </summary>
     4 /// <param name="e">描述如何访问此页的事件数据。
     5 /// 此参数通常用于配置页。</param>
     6 protected override void OnNavigatedTo(NavigationEventArgs e)
     7 {
     8     // TODO: 准备此处显示的页面。
     9  
    10     // TODO: 如果您的应用程序包含多个页面,请确保
    11     // 通过注册以下事件来处理硬件“后退”按钮:
    12     // Windows.Phone.UI.Input.HardwareButtons.BackPressed 事件。
    13     // 如果使用由某些模板提供的 NavigationHelper,
    14     // 则系统会为您处理该事件。
    15  
    16     Button btn = new Button();
    17     btn.Content = "代码创建的按钮";
    18     btn.Click += btnHello_Click;
    19     grid.Children.Add(btn);
    20 }
    通过C#代码创建控件

    虽然我们可以这样创建对象,但是这种形式就丧失我们XAML创建页面元素对象的优势了!

    总结一下:XAML只是创建对象的一种便捷方式,类似于一种“命令”的形式,跟后台代码没有关系,只是在后台执行的时候键xaml文件当做资源去载入罢了!

    结合这个几个平台来看,认为微软为开发者考虑的太多,有的时候反倒是形成一种“负担”!

  • 相关阅读:
    6-8 adaboost分类器2
    6-7 adaboost分类器1
    6-6 Haar特征3
    6-5 Haar特征2
    6-4 Haar特征1
    6-3 图片合成视频
    6-2 视频分解图片
    Linux操作系统六大优点
    Linux系统正则表达式用法笔记
    Linux系统正则表达式用法笔记
  • 原文地址:https://www.cnblogs.com/micua/p/windows-phone-xaml.html
Copyright © 2020-2023  润新知