前面已經介紹過,儘管XAML和WPF這兩種技術具備相互補充的做用,但他們也是相互獨立的。所以,徹底能夠建立不使用XAML和WPF應用程序。數據庫
總之,可以使用三種不一樣的編碼方式來建立WPF應用程序:app
1、只使用代碼函數
對於編寫WPF應用程序,只使用代碼進行開發而不適用任何XAML的作法並不常見(可是仍然徹底支持)。只使用代碼進行開發的明顯缺點在於,可能會使編寫WPF應用程序成爲極端乏味的工做。WPF控件沒有包含參數化的構造函數,所以即便爲窗口添加一個簡單按鈕也須要編寫幾行代碼。ui
只使用代碼進行開發的一個潛在的有點是能夠隨意定製應用程序。例如,可根據數據庫記錄中的信息生成充滿輸入控件的窗體,或可根據當前的用戶酌情添加或替換控件。須要的全部內容只不過是少許的條件邏輯。相比之下,若是使用XAML文檔,它們只能做爲固定不變的資源嵌入到程序集中。this
下面代碼用於生成一個普通窗體,該窗體包含一個按鈕和一個時間處理程序。在建立窗口時,構造函數調用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()方法中執行初始化操做。spa
爲啓動該應用程序,可在Main()方法中添加以下代碼:設計
public class Program:Application { [STAThread] public static void Main() { Program app = new Program(); app.MainWindow = new Window1(); app.MainWindow.ShowDialog(); } }
運行效果圖以下所示:code
2、使用代碼和未編譯的XAMLxml
使用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類將該文檔加載到一個已經存在的窗體中。檢測以後,爲了收集結果,只須要枚舉全部輸入控件並提取他們的內容便可。
3、使用代碼和編譯過的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應用程序。