标签:connect 配置 函数 不包含 项目文件 条件 方案 类继承 tle
前面已经介绍过,尽管XAML和WPF这两种技术具有相互补充的作用,但他们也是相互独立的。因此,完全可以创建不使用XAML和WPF应用程序。
总之,可使用三种不同的编码方式来创建WPF应用程序:
一、只使用代码
对于编写WPF应用程序,只使用代码进行开发而不适用任何XAML的做法并不常见(但是仍然完全支持)。只使用代码进行开发的明显缺点在于,可能会使编写WPF应用程序成为极端乏味的工作。WPF控件没有包含参数化的构造函数,因此即使为窗口添加一个简单按钮也需要编写几行代码。
只使用代码进行开发的一个潜在的有点是可以随意定制应用程序。例如,可根据数据库记录中的信息生成充满输入控件的窗体,或可根据当前的用户酌情添加或替换控件。需要的所有内容只不过是少量的条件逻辑。相比之下,如果使用XAML文档,它们只能作为固定不变的资源嵌入到程序集中。
下面代码用于生成一个普通窗体,该窗体包含一个按钮和一个时间处理程序。在创建窗口时,构造函数调用InitializeComponent()方法,该方法实例化并配置这个按钮和窗体,并连接(hook up)事件处理程序.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; namespace WPFCompileByCode { public class Window1:Window { private Button button1; public Window1() { InitializeComponent(); } private void InitializeComponent() { this.Width = 300; this.Height = 300; this.Left = 100; this.Top = 100; this.Title = "Code Only Window"; DockPanel panel = new DockPanel(); button1 = new Button(); button1.Content = "Click Me"; button1.Margin = new Thickness(30); button1.Click += button1_Click; IAddChild container = panel; container.AddChild(button1); container = this; container.AddChild(panel); } void button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Click Me"); } } }
从概念上讲,本例中的Windows1类更像传统的Windows窗体硬功程序中的窗体。它继承自Window基类,并为每个控件添加一个私有程序变量。为了清晰起见,该类在专门的InitializeComponent()方法中执行初始化操作。
为启动该应用程序,可在Main()方法中添加如下代码:
public class Program:Application { [STAThread] public static void Main() { Program app = new Program(); app.MainWindow = new Window1(); app.MainWindow.ShowDialog(); } }
运行效果图如下所示:
二、使用代码和未编译的XAML
使用XAML最有趣的方式之一是使用XamlReader类随时解析它。例如,假设创建一个Window1.xaml的文件,且内容如下所示:
<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Button Name="button1" Margin="30">Click Me</Button> </DockPanel>
编写一个类,用来加载xaml文件。如下代码所示:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; namespace WPFCompileByXaml { public class Window1:Window { private Button button1; public Window1(string xamlFile) { this.Width = 300; this.Height = 300; this.Left = 100; this.Top = 100; DependencyObject rootElement; using (FileStream fs = new FileStream(xamlFile, FileMode.Open)) { rootElement = (DependencyObject)XamlReader.Load(fs); } this.Content = rootElement; button1 = (Button)LogicalTreeHelper.FindLogicalNode(rootElement, "button1"); /* FrameworkElement frameworkElement = (FrameworkElement)rootElement; button1 = (Button)frameworkElement.FindName("button1"); */ button1.Click += button1_Click; } void button1_Click(object sender, RoutedEventArgs e) { //MessageBox.Show("Hello ,you click me!"); button1.Content = "Thank you!"; } } }
在此,构造函数接收XAML文件名作为参数。然后构造函数打开一个FileStream对象,并使用XamlReader.Load()方法将这个文件中的内容转换为DependencyObject对象,DependencyObject是所有WPF控件继承的基类。DependencyObject对象可放在任意类型的容器中,但在这个示例中它被用作整个窗体的内容。
为操作元素——如Windows1.xaml文件中的按钮,需要在动态加载的内容中查找相应的控件对象。LogicalTreeHelper类可达到该目的,因为它具有查找一颗完整控件对象的能力,它可以查找所需的许多层,直到找到具有指定名称的对象。然后将一个事件处理程序关联到Button.Click事件。
另外一种方法是使用FrameworkElement.FindName()方法,在这个示例中,根元素是DockPanel对象,与WPF窗口中的所有控件一样,DockPanel类继承自FrameworkElment类,这意味着可使用如下等效的方法:
FrameworkElement frameworkElement = (FrameworkElement)rootElement; button1 = (Button)frameworkElement.FindName("button1");
代替下面的代码:
button1 = (Button)LogicalTreeHelper.FindLogicalNode(rootElement, "button1");
在这个示例中,Window1.xaml文件和可执行的应用程序位于同一文件夹中,并一同发布。然而,尽管该文件没有被编译为应用程序的一部分,但仍可以将其添加到Visual Studio项目中。这样可以更方便地管理文件,并使用Visual Studio设计用户界面(假定使用.xaml文件扩展名,从而使用Visual Studio能够识别出该文档是XAML文档)。
如果使用这种情况,确保松散的XAML文件不会像传统的XAML文件那样被编译或嵌入到项目中。将文件添加到项目后,在解决方案中选中该文件,然后使用属性窗口,将Build Action设置为None,并将Copy to Output Directory 设置为Copy Always。
显然,先将XAML编译为BAML,再在运行时加载BAML,比动态加载XAML的效率高,当用户界面比较复杂时尤其如此。然而,这种编码模式为构建动态的用户界面提供了多种可能。例如,可创建通用的检测应用程序,从Web服务中读取窗体文件,然后显示相应的检测控件(标签、文本框和复选框等)。窗体文件可以是具有WPF标签的普通XML文件,使用XamlReader类将该文档加载到一个已经存在的窗体中。检测之后,为了收集结果,只需要枚举所有输入控件并提取他们的内容即可。
三、使用代码和编译过的XAML
当编译WPF应用程序时,Visual Studio使用分为两个阶段的编译处理过程。第一阶段将XAML文件编译为BAML。例如,如果项目中包含名为Window1.xaml的文件,编译器将创建名为Window1.baml的临时文件,并将该文件放在项目文件夹的obj/Debug字文件夹中。同时,使用选择的语言为窗口创建部分类。例如,如果使用C#语言,编译器将在obj/Debug文件夹中创建名为Window1.g.cs的文件。g代表生产的(generated)。
部分类包括如下三部分内容:
部分类不包含实例化和初始化控件的代码,因为这项任务由WPF引擎在使用Application.LoadComponent()方法处理BAML时执行。
具体实例,可以查看Visual Studio编译后的WPF应用程序。
标签:connect 配置 函数 不包含 项目文件 条件 方案 类继承 tle
原文地址:https://www.cnblogs.com/Peter-Luo/p/12150734.html