WPF教程一:創建Hello world來理解XAML的內容及編譯


  在實際的WPF開發中遇到很多再用Winform寫法來寫WPF的開發人員,很多時候項目進度延期、出現非必要的BUG等等、大多是因為開發人員雖然是再寫WPF。

但是沒有好好的學過WPF,就導致無法發揮出WPF的優勢、很多地方都是開個線程處理完成后一個回調UI線程函數里面套一整段代碼,這種情況下不僅難處理多線程問題、也會出現很多偶發性的BUG,不好追蹤問題在哪里。同時也會因為開發人員對WPF的理解參差不齊導致架構設計和使用過程中代碼凌亂。所以今天開始hello world 來梳理WPF。

我們通過hello world理解以下幾個關鍵內容來整理XAML相關的知識點:

一、使用XAML創建可以顯示hello world的文本框。

二、理解XAML中的文法規范級命名空間

三、XAML中的的屬性和事件

四、從生成過程日志查看XAML的編譯。

 

一、使用XAML創建可以顯示hello world的文本框

  經常寫winform窗體的同學一定深有感觸、拿到UI給的圖之后、我們如果想做的比較漂亮。大部分都是通過拖控件、然后把用戶界面的后台代碼中設置動畫效果、大小、位置等等。如果需要適配多種分辨率是更難受的。特別是一些需要深度定制的東西、可能很多開發時間都會用在這里。解決一些稀奇古怪被測試出來的的顯示問題。

  而在WPF中提出了XAML的概念、我們可以使用XAML標簽來設計和構成我們的用戶界面。而XAML豐富的標簽一旦正確的使用,則會大大提高我們寫出更漂亮的界面的能力。

只寫文字大家都會反感。我們通過講解例子來認識XAML。首先創建一個WPF工程。

1、寫下第一行Hello world

打開VS選擇創建WPF項目,點擊下一步。

設置項目名稱為Hello World點擊創建。就創建了我們第一個WPF項目。

 

 通過解決方案標簽項我們可以看到整個解決方案的目錄結構。而項目中的MainWindow就是我們本次分析的重點。

 

 我們這次的重點在MainWindow.xaml和其對應的cs,所以其他部分不是本次的關注重點,也就不講了。

首先雙擊MainWindow.xaml,在Grid標簽中添加<TextBox Text="Hello world!"/>節點。然后在VS中按下F5鍵。程序就會執行編譯,如果成功的話就會跑起來,並且看到我們輸入的Hello world!。

<Window x:Class="HelloWorld.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:HelloWorld"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox Text="Hello world!"/>
    </Grid>
</Window>

 

從我們看到這個顯示出來的hello world!的這一刻開始,就正式開始了本章內容的講解。 

二、理解XAML中的文法規范級命名空間

 1 <Window x:Class="HelloWorld.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:HelloWorld"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">
 9     <Grid>
10         <TextBox Text="Hello world!"/>
11     </Grid>
12 </Window>

為了方便理解,我加入了行號,如果想系統的學習XAML可以先學習一下XML,XAML是遵循XML文法規范的,但是對於我們入門來說了解嵌套、 屬性的賦值和設置,就可以了。

我們的整體XAML結構大致為

<Window>

  <Grid>

    <TextBox/>

  </Grid>

</Window>

 

我們當前的XAML根節點是一個Window節點,Window節點代表當前所顯示的整個窗口、在Window節點內部有一個Grid節點,Grid節點是一個布局元素里面可以放置的所有的控件、Grid節點包含了一個內部的TextBox節點,而這個TextBox就是我們所說的控件,而我們看到的顯示的內容是在Text=“”內賦值的。對於XAML中的內容。可以理解為把后台的.cs代碼文件通過xaml可視化的方式進行設置,如果有不知道含義的地方,可以用鼠標點在對應的節點上然后按F12就可以跳轉到對應的定義中。

  比如我們把光標點在Grid上。按下F12。就會跳轉到下圖的位置。原來Grid繼承自一個Panel。里面包含了Column、Row等等。我們就知道了。Grid是一個擁有橫、列的網格面板。

 而在TextBox上按F12之后,就會看到這是一個控件、顯示或編輯文本的。

其他的元素同樣的道理。把鼠標放置在對應的元素節點上按下F12就會顯示對應的內容。

 

接下來我們來看命名空間。

名稱空間看上去好像是一個URI的WEB位置,但實際上不是,URI格式的命名空間,不同組織就基本不會使用相同的名稱空間創建不同的基於XAML的語言。

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 是WPF核心名稱空間。 它包含了所有WPF類,包括創建界面的控件。
該名稱空間沒有使用前綴、所以它成為整個文檔的默認命名空間。也就是說除非指明了名稱空間,否則每個元素都直接使用這個名稱空間。
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 是XAML名稱空間,它包含各種XAML的特性,該命名空間被映射為前綴x。可以在元素名稱之前放置x
來使用該名稱空間。例如x:Name,x:Class="HelloWorld.MainWindow"。
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"是旨在提供設計師支持,該名稱空間使XAML元素上的這些屬性僅影響XAML行為的設計方面。
而在運行過程中會忽略掉這些屬性。比如d:DesignHeight="100" d:DesignWidth="100",這個在設計時看不到該控件時,在對應的控件上添加此屬性特別有效。
在Blend下使用比較多的是針對集合的d:DataContext、d:DesignData。等等。感興趣的可以看看Blend相關的。
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 標識使運行時XAML解析器能夠忽略設計屬性,比如mc:Ignorable:d。d前綴的在運行時XAML解析器解析時就會忽略了。
xmlns:local="clr-namespace:HelloWorld" 這個就是我們工程自己的名稱空間了。

x:Class="HelloWorld.MainWindow" x:Class特性是告訴XAML解析器用指定的名稱生成一個新類,該類繼承自XAML元素命名的類,也就是我們的根節點Window。

三、理解XAML中的的屬性和事件

 XAML中的屬性:

我們通過前面的講解了通過跳轉查看XAML節點的含義,比如<Grid>是布局用的Panel。<TextBox/>是顯示和編輯無格式文本的。
那么現在我們來理解屬性。
在元素中我們通過跳轉了解到了XAML節點都是一個一個的類對象。里面定義了屬性、方法及事件。那么在XAML中,我們可以在這里設置屬性、事件。通過設置這些來修改樣式及監聽對應的事件消息。
那么在屬性中分為簡單屬性和復雜屬性。我們在Textbox上按F12跳轉過去,然后我們找個屬性來演示一下簡單屬性和復雜屬性如何使用。

 

 在Foreground上我們看到了該屬性是一個Brush類型。而在WPF中Brush支持純色、線性漸變色等等。我們設置代碼如下。

 

 這樣我們就在第一個TextBox 上設置了背景色為一個枚舉值。用於表示一個顏色值。 而當我們想設置復雜Brush的時候,我們就可以使用復雜屬性,第二個TextBox通過屬性的嵌套來創建一個復雜的線性畫刷。2個TextBox顯示效果如下:

  

 但是新的問題又來了,現在大部分主流的App都支持更換皮膚,明暗主題什么的。而我們只能通過硬編碼的形式設置屬性,那豈不是要實現更換皮膚,每個控件都要設置一遍?

有沒有什么辦法能讓XAML屬性綁定一個變量,而我們去修改這個變量?

實現方法的辦法之一就是使用擴展標記:假設我們的內容都放在一個windows里做演示:

 

 添加window的資源。同時使用DynamicResource來綁定資源。就可以實現。一個資源修改,所有使用的地方都跟着變化。后面會詳細講到。如何使用擴展標記來進行主題切換。

而在WPF中提出的是依賴項屬性的概念。這個和路由事件需要花費精力好好學一下。才能更好的使用和理解WPF。

 XAML中的事件:

為了增強事件的傳播能力,WPF中提出了路由事件的概念,路由事件可以在元素樹中向上和向下傳播,並且沿着傳播路徑被事件處理程序消費。我們在XAML中添加2個處理按下和抬起事件的代碼。

 

后台的處理代碼。

  

 路由事件和依賴項屬性這些主要會放在MVVM中講。這里主要了解一下。XAML下如何創建事件處理程序。

四、從生成過程日志查看XAML的編譯。

對於加載和編譯XAML,有四種方式:

1、只使用代碼來創建XAML對應的元素,類似於winform的寫法;

2、使用代碼和未經編譯的XAML。

3、使用代碼和編譯過的XAML。

4、只使用XAML。

這里我們只去理解一個使用代碼和編譯過的XAML。其他的工作到目前未知,覺得用到的比較少,等真正用到了。只要理解了可以在去查如何使用。

當我們編譯WPF程序時,編譯過程分為了2個階段,第一個個階段是將XAML文件編譯為BAML文件。我們使用的C#語言,所以會在臨時文件生成對應的.g.cs文件

g代表generated。

當從XAML到BAML的編譯結束后,編譯器會編譯代碼和生成的部分類文件。編譯過的代碼會變成單個程序集。每個窗口的BAML都會作為獨立資源被嵌入到程序集中。

我們通過修改VS的設置來查看編譯過程。

在VS選擇工具=>選項=>項目和解決方案=>生成並運行=>MSBuild項目生成輸出詳細程序=>設置為詳細。而后點擊編譯。我們來觀察輸出的內容。

 

我們查看關鍵的幾處

 

 

 

  

 

 

以上截圖就是完整的編譯過程。

 

 

我創建了一個C#相關的交流群。用於分享學習資料和討論問題。歡迎有興趣的小伙伴:QQ群:542633085

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM