ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【WPF】MainWindow.xaml和MainWindow.g.i.cs 文件相对应

2022-07-26 23:02:46  阅读:151  来源: 互联网

标签:文件 xaml System cs 方法 MainWindow


  一个 MainWindow.xaml 文件和一个 MainWindow.g.i.cs 文件相对应。

 

如上图所示窗口类文件被定义为partial的就是因为类 MainWindow 在 MainWindow .g.i.cs文件中还有定义,如下

 

public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector

在MSDN中查看该接口的说明:

 

 (显然,这个中文的翻译是机器翻译的。)IComponentConnector接口的功能是:解析 MainWindow.xaml 文件然后将该文件中所有标签中具有Name或x:Name属性的标签声明与该标签对应的对象,例如在MainWindow.xaml中下面的标签

 

 在 MainWindow.g.i.cs 文件中生成了如下的语句

这也就解释了为什么我们可以直接在 MainWindow.xaml.cs文件中的类MainWindow可以直接使用由x:Name或Name来标示的对象------ 因为他们都在 MainWindow.g.i.cs 文件中进行了声明。但是光有这些声明是不能够使用这些对象的,因为他们没有被初始化! 这一就是为什么在 MainWindow.g.i.cs 文件中定义的 MainWindow 类还要实现接口 IComponentConnector 的原因----- 初始化上面那些组件。 初始化的过程有两步: 第一步:在内存中构建这些对象的实例(对应接口IComponentConnector中的InitializeComponent方法); 第二步:将第一步中内存中的对象实例赋给上面那些声明的对象引用,这样这些引用才能够使用(对应接口IComponentConnector中的Connect方法)。

IComponentConnector 接口有两个方法:

 

  public interface IComponentConnector
    {
        void Connect(int connectionId, object target);
        void InitializeComponent();
    }

下面为InitializeComponent方法的一个实现

 
 public void InitializeComponent()

{

            if (_contentLoaded) {

                return;

            }

            _contentLoaded = true;

            System.Uri resourceLocater = new System.Uri("/WpfApplication1;component/mainwindow.xaml", System.UriKind.Relative);

           

            #line 1 "..\..\..\MainWindow.xaml"

            System.Windows.Application.LoadComponent(this, resourceLocater);

}

 

显然这个方法的作用就是:① 加载 MainWindow.xmal 文件;② 解析该XMAL文件,并在内存中构造该xaml文件中出现的命名对象。(参考msdn中对Application.LoadComponoent方法的说明:加载位于指定uniform resource identifier (URI) 处的 XAML 文件,并将其转换为由该 XAML 文件的根元素指定的对象的实例。)

void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target)

switch (connectionId)
case 1:
this.mainWindow = ((WpfApplication1.MainWindow)(target));

#line 4 "..\..\..\MainWindow.xaml"
this.mainWindow.Loaded += new System.Windows.RoutedEventHandler(this.mainWindow_Loaded);
return;

case 2:
this.label1 = ((System.Windows.Controls.Label)(target));
return;

case 3:
this.label2 = ((System.Windows.Controls.Label)(target));
return;

case 4:
this.textBoxName = ((System.Windows.Controls.TextBox)(target));
return;
this._contentLoaded = true;

在考虑这几个函数的调用过程。

1.在MainWindow.xaml.cs文件中MainWindow类的构造函数调用了MainWindow.g.i.cs中的InitializeComponent方法

 

 2. 在看InitializeComponent方法的实现,最后调用了LoadComponent方法,可以猜想InitializeComponent方法一定调用了Connect方法来实现应用对象的初始化。(如果这个方法没有调用Connect方法,那么上面那些对象就无法被实例化,就不能在MainWindow类中使用了)

下面通过扒源码来证明上面的猜想:

(1).将上面的项目生成的PE文件WpfApplication1.exe进行反编译,

 

 

 

(2).找到InItializeComponent方法的实现

 

 

 (3). 进入Application.LoadComponent方法的实现

 

 结合LoadComponent方法签名,可知该方法将this对象传给了XamlReader.LoadBaml方法

(4). 进入XamlReader.LoadBaml方法,该方法的签名如下:

 

 

 

 

(5). 跟进WpfXamlLoader.LoadBaml方法

 

 

 

(6). 跟进Load方法

 

 

 

(7). 跟进TransformNodes方法

 

 

 

总结:InitializeComponent方法确实调用了Connect方法。

同时我们也知道了WPF中的一个窗口是由3个文件组成的*.xaml,*.xaml.cs,*.g.i.cs

 

如上图,在InitializeComponent方法之前使用了 label1 对象,给该对象设置宽度。注意下面,编译成功了!但是这个程序是无法执行的,因为label1是null,所以this.label1.Width = 100这个赋值操作会出现异常。

标签:文件,xaml,System,cs,方法,MainWindow
来源: https://www.cnblogs.com/cdaniu/p/16522998.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有