创建WPF程序的三种方式:
1.只使用代码
2.使用代码和未经编译的标记(XAML)
3.使用代码和编译过的标记(BAML)
第一种不写了,比较简单
第二种:
所谓的第二种方法就是直接读一个XAML文件,解析它并创建界面元素,要注意的是要读的XAML文件属性要设置成如下的样子
private Button button1;上面直接把Window1.xaml从硬盘读到文件流中,再转化成DependencyObject对象,DependencyObject是所有WPF控件继承的基类.
public Window1(string xamlFile)
{
InitializeComponent(xamlFile);
}
private void InitializeComponent(string xamlFile)
{
// Configure the form.
this.Width = this.Height = 285;
this.Left = this.Top = 100;
this.Title = "Dynamically Loaded XAML";
// Get the XAML content from an external file.
DependencyObject rootElement;
using (FileStream fs = new FileStream(xamlFile, FileMode.Open))
{
rootElement = (DependencyObject)XamlReader.Load(fs);
}
// Insert the markup into this window.
this.Content = rootElement;
// Find the control with the appropriate name.
//button1 = (Button)LogicalTreeHelper.FindLogicalNode(rootElement, "button1");
FrameworkElement frameworkElement = (FrameworkElement)rootElement;
button1 = (Button)frameworkElement.FindName("button1");
// Wire up the event handler.
button1.Click += new RoutedEventHandler(button1_Click);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
button1.Content = "Thank you.";
}
}
上面被注释的代码
button1 = (Button)LogicalTreeHelper.FindLogicalNode(rootElement, "button1");与
FrameworkElement frameworkElement = (FrameworkElement)rootElement; button1 = (Button)frameworkElement.FindName("button1");是等效的, LogicalTreeHelper是一个辅助类,具有查找一棵完整控件对象树的能力,这个示例中XAML文件中的根元素是DockPanel,DockPanel又继承自 FrameworkElement类,所以使用FrameworkElement.FindName()方法同样可以找到控件对象.
第三种:
这种方法是VS自己支持的,所有代码都是自动生成的,不用我们人为去编码,即把XAML编译成BAML文件,再嵌入dll中作为资源保存,程序运行时再从dll中读出来. 读BMAL比直接读XMAL文件效率要高,因为BMAL已经经过了优化,文件体积也比XMAL小. 编译器在编译成会生成一个BMAL文件,和一个分部类,它们会放在项文件夹的obj\Debug子文件夹中.
下面来看看这个VS自动生成的部分类,Window1.g.cs (只呈现主要逻辑代码,省略掉非关键部分)
/// <summary> /// Window1 /// </summary> public partial class Window1 : System.Windows.Window, System.Windows.Markup.IComponentConnector { internal System.Windows.Controls.TextBox txtQuestion; internal System.Windows.Controls.Button cmdAnswer; internal System.Windows.Controls.TextBox txtAnswer; #line default #line hidden private bool _contentLoaded; /// <summary> /// InitializeComponent /// </summary> public void InitializeComponent() { if (_contentLoaded) { return; } _contentLoaded = true; System.Uri resourceLocater = new System.Uri("window1.baml", System.UriKind.Relative); System.Windows.Application.LoadComponent(this, resourceLocater); #line default #line hidden } ...... void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { switch (connectionId) { case 1: this.txtQuestion = ((System.Windows.Controls.TextBox)(target)); return; case 2: this.cmdAnswer = ((System.Windows.Controls.Button)(target)); this.cmdAnswer.Click += new System.Windows.RoutedEventHandler(this.cmdAnswer_Click); return; case 3: this.txtAnswer = ((System.Windows.Controls.TextBox)(target)); return; } this._contentLoaded = true; } }
方法二中的XamlReader用处很大,下面的代码摘自 这个地方
通过XamlReader 动态构建并实例化一个Window
//XamlReader StringBuilder strXMAL = new StringBuilder("<Window ");strXMAL.Append("xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" ");strXMAL.Append("xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" ");strXMAL.Append("Title=\"Window2\" Height=\"600\" Width=\"600\">");strXMAL.Append("</Window>");var window = (Window)XamlReader.Parse(strXMAL.ToString());window.ShowDialog();
作者还自己实现了BMAL文件的Reader和Writer,有兴趣可以研究研究,一般情况下也用不上的