WPF學習筆記02-XAML語法

来源:https://www.cnblogs.com/iceamos/archive/2023/03/01/17168599.html
-Advertisement-
Play Games

上一章我們對XAML有個初步的認識了,知道XAML是用來設計UI的,那麼說怎麼設計,基本用法和語法分別是什麼呢?接下來我們就系統的簡單學習一下XAML的一些基本語法吧。 1 - XAML的結構 如果學習過Winform或者其他桌面設計的應該知道我們最終設計的是與人員交互的圖形界面。比如在Winfor ...


上一章我們對XAML有個初步的認識了,知道XAML是用來設計UI的,那麼說怎麼設計,基本用法和語法分別是什麼呢?接下來我們就系統的簡單學習一下XAML的一些基本語法吧。

1 - XAML的結構

如果學習過Winform或者其他桌面設計的應該知道我們最終設計的是與人員交互的圖形界面。比如在Winform當中你去設計界面之後,VS自動給你生成了design.cs,我們打開能夠看到裡邊首先是聲明瞭對應的類,然後設置了對應類的屬性。對於xaml而言也差不多,不過唯一的區別就是,xaml的結構相對於其他設計型而言是屬於樹結構。我們知道一棵樹有對應樹幹,樹幹有很多分支,分支上邊又可以有很多分支。這個就是樹結構。xaml就是如此。

在Winform當中比如我們設計一個

其中上邊控制項一般情況下是我們預設拖上去的,當我們查看design.cs中發現是沒有層級結構的

但是在xaml中如果要設計同樣的界面,是需要在樹結構的基礎上去設計對應界面

在WPF中基本摒棄掉了傳統Winform的拖拉控制項式佈局,上面界面的代碼如下:

 1 <Window
 2     x:Class="FirstWPFDemo.MainWindow"
 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 6     xmlns:local="clr-namespace:FirstWPFDemo"
 7     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8     Title="MainWindow"
 9     Width="225"
10     Height="250"
11     mc:Ignorable="d">
12     <StackPanel Margin="15">
13         <StackPanel Margin="5" Orientation="Horizontal">
14             <Label Content="姓名:" />
15             <TextBox
16                 Width="120"
17                 Height="30"
18                 VerticalAlignment="Top" />
19         </StackPanel>
20         <StackPanel Margin="5" Orientation="Horizontal">
21             <Label Content="性別:" />
22             <RadioButton VerticalAlignment="Center" Content="男" />
23             <RadioButton VerticalAlignment="Center" Content="女" />
24         </StackPanel>
25         <StackPanel Margin="5" Orientation="Horizontal">
26             <Label Content="年級:" />
27             <ComboBox Width="120" VerticalAlignment="Center">
28                 <ComboBox.Items>
29                     <ComboBoxItem Content="請選擇" IsSelected="True" />
30                     <ComboBoxItem Content="一年級" />
31                     <ComboBoxItem Content="二年級" />
32                 </ComboBox.Items>
33             </ComboBox>
34         </StackPanel>
35         <Button
36             Width="60"
37             Margin="0,5,20,0"
38             HorizontalAlignment="Right"
39             Content="保存" />
40     </StackPanel>
41 </Window>

 

我們能夠看到就是在Window的樹幹下邊有了StackPanel,在StackPanel下又有多個容器和按鈕。最終構成了對應的界面。不難看出這個就是在樹形結構的基礎上,延伸出來的構造。

2 - 為對象屬性賦值的語法

在上述Demo中,雖然你現在還不知道怎麼佈局,怎麼設置屬性。但是其中我們能夠觀察到最簡單的一些賦值,比如當我們給Button按鈕賦值文本的時候,我們直接設置的是Button的Content屬性。如<Button Conent="點我" />這種設置。這種呢我們叫做簡單的字元串屬性設置。

2.1 - 簡單屬性賦值

比如我們現在需要設置一個寬度為150,高度為40,字體大小為15,字體顏色為藍色,預設文本是“你好,WPF”的文本輸入框那麼我們需要這麼設置

<TextBox Width="150" Height="40" FontSize="15" Foreground="Blue" Text="你好,WPF"/>

其中呢,Width為寬度,Height為高度,FontSize為字體大小,Text為文本內容。Foreground為字體顏色

實現內容為

此時不知道作為初學者的你發沒發現一個問題。我設置的所有屬性都是字元串類型。但是界面渲染的時候還是按照對應屬性進行的渲染,比如顏色。我設置的是字元串類型的值,後臺是如何知道是顏色呢?這就需要我們學習到一個知識點叫做:類型轉換器

2.2 - 類型轉換器

它可以將任何特定類型的數據轉換為其他類型,同理,也可以將其他任何類型轉換為特定的數據類型。比如剛纔咱們介紹的那種情況。賦值賦的是字元串類型,但是渲染出來還是顏色。其實XAML解析器通過兩個步驟查找到了對應的類型轉換器。

1)檢查對應的屬性聲明。比如Foreground屬性,查看是否存在TypeConverter特性。如果提供了,即證明將指定哪種類型進行轉換。【比如Width、Height等】如果要深究LengthConverter等是怎麼工作的之後可以看看WPF源碼,簡單介紹下,所欲的類型轉換器都繼承於TypeConverter 都重寫了CanConvertFrom CanConvertTo 和 ConvertFrom。賦值時會先判斷所輸入是否能夠完成轉換。其他的可以直接去看源代碼

 1 [TypeConverter(typeof(LengthConverter))]
 2 [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
 3 public double Height
 4 {
 5     get
 6     {
 7         return (double)GetValue(HeightProperty);
 8     }
 9     set
10     {
11         SetValue(HeightProperty, value);
12     }
13 }

 

2)如果再屬性聲明中沒有TypeConverter特性,XAML解析器將檢查對應類的聲明,如,Foreground屬性使用了Brush對象,由於Brush使用TypeConverter(typeof(BrushConverter))特性聲明進行了修飾,因此Brush類及其子類使用BrushConverter類型轉換器。可以直接F12查看

 1 [Bindable(true)]
 2 [Category("Appearance")]
 3 public Brush Foreground
 4 {
 5     get
 6     {
 7         return (Brush)GetValue(ForegroundProperty);
 8     }
 9     set
10     {
11         SetValue(ForegroundProperty, value);
12     }
13 }

 

我們寫個Demo來驗證下對應的映射關係

首先新建一個Person類

 1 /// <summary>
 2 /// Person 人員類
 3 /// </summary>
 4 public class Person
 5 {
 6     //人員姓名
 7     public string PerName { get; set; }
 8     //人員類別
 9     public Person PerChild { get; set; }
10 }

 

此時我們在界面上使用新建的類(其中部分語法可能看不懂之後會說到)

1 <Window.Resources>
2     <local:Person
3         x:Key="per"
4         PerChild="李四"
5         PerName="張三" />
6 </Window.Resources>

 

新建一個Button按鈕,當點擊的時候我們獲取到PerChild並彈窗

1 <Button
2     Width="120"
3     Height="50"
4     Click="Button_Click"
5     Content="點 我" />
1  private void Button_Click(object sender, RoutedEventArgs e)
2 {
3     var per = this.FindResource("per") as Person;
4     MessageBox.Show(per.PerChild.PerName);
5 }

 

我們編譯之後發現能夠編譯成功,但是有對應的提示這是為什麼呢?因為我們後臺定義的PerChild是Person類型的,我們是沒辦法直接從string類型的醫生轉換為對應類別類型的。怎麼去處理這個問題呢?

1)我們首先聲明一個類型轉換器StringToPersonTypeConverter

 1 /// <summary>
 2 /// string類型轉換Person轉換器
 3 /// </summary>
 4 public class StringToPersonTypeConverter : TypeConverter
 5 {
 6      public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
 7     {
 8         //如果值為string類型的值時
 9         if (value is string)
10         {
11             Person per = new Person();
12             per.PerName = value as string;
13             return per;
14         }
15         return base.ConvertFrom(context, culture, value);
16     }
17 }

 

2) 聲明完成之後再Person上邊加上對應特性

1 [TypeConverterAttribute(typeof(StringToPersonTypeConverter))]

 

此時我們再重新運行的時候就可以彈出對應李四了。

2.3 - 複雜屬性賦值

有一些屬性是完備的對象,有自己的一組屬性。在簡單屬性直接賦值的基礎上衍生出對應的屬性元素語法。屬性元素指的是某個標簽的一個元素對應這個標簽的一個屬性。如

<ClassName>
  <CalssName.PropertyName>
    <!--為屬性賦值-->
  </CalssName.PropertyName>  
</ClassName>

比如,就簡單在界面上畫一個矩形

1 <Rectangle
2     Width="50"
3     Height="50"
4     Margin="0,50"
5     Fill="Blue" />

 

那麼說問題來了,眾所周知,對於WPF而言,渲染和動畫也是比較亮點的功能。假如此時有個需求背景不僅僅是純藍色,而是漸變色,怎麼去處理,只是使用簡單的屬性賦值Fill="Blue"已經滿足不了當前需求了,這時候應該怎麼做呢?【先不用關心你不認識的對象後邊會介紹到】

 1 <Rectangle
 2     Width="50"
 3     Height="50"
 4     Margin="0,50">
 5     <Rectangle.Fill>
 6         <LinearGradientBrush>
 7             <LinearGradientBrush.GradientStops>
 8                 <GradientStop Offset="0" Color="Red" />
 9                 <GradientStop Offset="0.5" Color="Yellow" />
10                 <GradientStop Offset="1" Color="Blue" />
11             </LinearGradientBrush.GradientStops>
12         </LinearGradientBrush>
13     </Rectangle.Fill>
14 </Rectangle>

 

其中<Rectangle.Fill>中使用了線性漸變畫刷來填充【後續介紹Brush時會提及到】。此時此刻我們就能感覺到,簡單賦值完不成的使用複雜屬性賦值的方式的優勢就體現出來了。界面如下

2.4 - 標記擴展

正常情況下對於xaml而言,屬性賦值這塊已經比較好了,但是我們發現我們的賦值都是固定的,屬於硬性編碼複製,假如我想將一個對象的值賦值給某個屬性或者將一個控制項的值賦值給另外一個控制項時這時候我們怎麼處理?這時候就要用到我們所說的標記擴展了。標記擴展是一種非常規的方式設置屬性的語法。【其實就是一種特殊的簡單賦值】

設置語法:{標記擴展類 參數}

使用花括弧括起來。比如我們給文本框的字體顏色賦值

<TextBox Text="你好,WPF!" Foreground="Blue" />
<TextBox Text="你好,WPF!" Foreground="{x:Static SystemColors.ActiveBorderBrush}" />

其實兩者都實現了給對應前景色賦值,不過一個使用了簡單屬性賦值方式一個使用了標記擴展的方式。下者是獲取了系統顏色裡邊的控制項激活時的顏色。

我們寫一個Demo吧,這個Demo是實現當我們滑動控制項時變更Label字體的大小。

1 <Slider
2     x:Name="s"
3     Maximum="20"
4     Minimum="10" />
5 <Label Content="Demo字體大小" FontSize="{Binding ElementName=s, Path=Value}" />
6 <TextBox Text="{Binding ElementName=s, Path=Value}" />

 

實現效果如圖所示【先不需要關心Binding這些後續會有專門介紹】

2.5 - 附加屬性

附加屬性,顧名思義就是附加上去的屬性。在WPF中附加屬性一般都常用語控制項佈局方面【後續有專門介紹佈局章節】附加屬性始終使用包含兩部分的命名格式:定義類型.屬性名

附加屬性其實根本不是真正的屬性。實際上被轉為方法來調用了,最終調用的是靜態方法DefiningType.SetPropertyName()。我們寫個小Demo就能看出來附加屬性的基本使用方法了。

 1 <Grid>
 2    <Grid.ColumnDefinitions>
 3        <ColumnDefinition Width="50" />
 4        <ColumnDefinition Width="50" />
 5    </Grid.ColumnDefinitions>
 6    <Grid.RowDefinitions>
 7        <RowDefinition Height="50" />
 8        <RowDefinition Height="50" />
 9    </Grid.RowDefinitions>
10    <TextBox Text="你好,WPF!" Margin="5" Foreground="Blue" Grid.Column="0" Grid.Row="0" />
11    <TextBox Text="你好,WPF!" Margin="5" Foreground="Orange" Grid.Column="1" Grid.Row="1" />
12 </Grid>

 

我們定義了兩行兩列,分別放置了兩個TextBox。其中Grid.Row=“0”這個就叫做附加屬性。附加屬性是WPF的核心要素之一。比如將Row屬性定義為附加屬性,可以確保所有控制項都可以使用他,即使我們把TextBox控制項換成Button、Radio、ComboBox等等。

3 - 事件

以上我們介紹的所有特性都被映射為了Property屬性。其實特性也可以關聯事件處理程式。比如Button按鈕標簽有個特性叫Click的閃電形狀。它就是Button類的Click事件【如果對於寫過Winform的來說並不陌生】

語法:事件名稱=“事件處理程式的方法名”

<Button Content="點擊我彈窗" Click="Button_Click"/>

在Click事件名稱上點擊F12進入後臺事件編寫上邊

1 private void Button_Click(object sender, RoutedEventArgs e)
2 {
3     MessageBox.Show("你好呀!");
4 }

 

在這個事件當中我們可以寫我們對應的代碼邏輯。在WPF中事件模型和其他類型.NET應用程式事件模型不通。WPF的事件模型依賴於事件。之後詳解。

其中WPF生成對應事件名稱規則,是如果對應對象有name屬性則生成name_事件名稱比如Click,name為btn。則生成的為btn_Click。如果沒有name屬性則預設生成類名_事件名稱比如Click預設為Button_Click。

4 - 引用命名空間

一般情況下我們寫的項目不可能只有一個,當我們需要引用其他程式集或者其他模塊的時候,我們需要引用對應的命名空間。我們在上一節已經介紹過了命名空間如何引用。語法為xmlns[可省略的首碼名]:"命名空間所在位置"

其中當我們需要引用對應程式集時,語法為

xmlns[首碼名]:"clr-namespace:Namespace;assembly=AssemblyName"

當我們實戰項目經驗多了,就會發現這個引用命名空間其實很簡單。

以上呢就是這節介紹的xaml的一些基本語法。其中一些demo還需要自己練習。下邊進入xaml的UI學習。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 又到了所謂的金山銀四就業季,那找工作的小伙伴宿舍住不慣的話,就會去租房子住,當然也不一定有宿舍,那麼自己找房子的話,肯定是不知道哪哪好。 所以今天教大家用Python來採集本地房源數據,幫助大家篩選好房。 本文涉及知識點 爬蟲基本流程 requests 發送請求 parsel 解析數據 csv 保存 ...
  • 一、什麼是繼承 繼承是一種新建類的方式,新建的類稱為子類,被繼承的類稱為父類 繼承的特性是:子類會遺傳父類的屬性 繼承是類與類之間的關係 二、為什麼用繼承 使用繼承可以減少代碼的冗餘 三、對象的繼承 Python中支持一個類同時繼承多個父類 class Parent1: pass class Par ...
  • Synchronized鎖優化 jdk1.6對鎖的實現引入了大量的優化,如自旋鎖、適應性自旋鎖、鎖消除、鎖粗化、偏向鎖、輕量級鎖等技術來減少鎖操作的開銷。 鎖主要存在四中狀態,依次是:無鎖-> 偏向鎖 -> 輕量級鎖 -> 重量級鎖,他們會隨著競爭的激烈而逐漸升級。註意鎖可以升級不可降級,這種策略是 ...
  • 昨晚回家,表弟在看LOL直播,看得我氣不打一處來,差點就想錘他。 身為程式員的表弟,看直播發彈幕居然還在手動發,當時我就用Python寫了一個自動發送彈幕的腳本送給他用。 好了話不多說,我們直接開搞! 先看看效果 名字我就打碼了,當然名字不是關鍵,我直接截圖展示算了,GIF的話,太麻煩了。 接下來我 ...
  • Adobe Lightroom 鍵盤快捷鍵 Adobe Lightroom CC 中 251 個鍵盤快捷鍵的可視化備忘單鍵盤快捷鍵,為開發人員分享快速參考備忘單。 開發速查表大綱 鍵盤快捷鍵 使用面板 導航模塊 使用輔助視窗 在開發模塊中工作 更改視圖和屏幕模式 管理照片和目錄 比較圖庫模塊中的照片 ...
  • 聲明 本文章中所有內容僅供學習交流,抓包內容、敏感網址、數據介面均已做脫敏處理,嚴禁用於商業用途和非法用途,否則由此產生的一切後果均與作者無關,若有侵權,請聯繫我立即刪除! 本文章未經許可禁止轉載,禁止任何修改後二次傳播,擅自使用本文講解的技術而導致的任何意外,作者均不負責,若有侵權,請在公眾號【K ...
  • Integer使用==比較的問題 new一個對象 public Integer(int value) { this.value = value; } 自動裝箱 public static Integer valueOf(int i) { if (i >= IntegerCache.low && i ...
  • 最近在忙於 Fireasy 的重構,3.x 拋棄了 .Net Framework 時代的一些思想和模式,緊密擁抱 .Net Core,但它的思想仍然是開放性和靈活性。今天我主要來說說依賴註入與服務發現。 .Net Core 有自己的一套依賴註入,它的容器暴露給 IServiceCollection, ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...