# WPF複習知識點記錄 由於近幾年主要在做Web項目,客戶端的項目主要是以維護為主,感覺對於基礎知識的掌握沒有那麼牢靠,趁著這個周末重新複習下WPF的相關知識。 文章內容主要來自大佬劉鐵錳老師的經典著作《深入淺出WPF》。 因為是複習,所以知識內容不會一一記錄,如有需要瞭解更多可以看書中內容。 * ...
WPF複習知識點記錄
由於近幾年主要在做Web項目,客戶端的項目主要是以維護為主,感覺對於基礎知識的掌握沒有那麼牢靠,趁著這個周末重新複習下WPF的相關知識。
文章內容主要來自大佬劉鐵錳老師的經典著作《深入淺出WPF》。
因為是複習,所以知識內容不會一一記錄,如有需要瞭解更多可以看書中內容。
註意:博客中的代碼示例我是以avalonia為UI框架寫的。代碼可能部分跟WPF的稍有不同。
1.從零起步認識XAML
1.什麼是XAML
XAML(讀作zaml)是WPF技術中專門用於設計UI 的語言
2.優點
- 實現界面與代碼的分離
- 可以設計出專業的UI和動畫
- 基於XML的標記語言,簡單易懂,結構清晰
3.XAML剖析
1.最簡單的XAML代碼
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
</Window>
這個示例中,Window
是一個XAML元素,它表示視窗組件。xmlns
屬性定義了XML命名空間,即指明XAML所使用的命名空間。在這裡,http://schemas.microsoft.com/winfx/2006/xaml/presentation
是WPF的命名空間。
這個示例中的XAML代碼只有一個Window
元素,它是一個空的容器。可以在Window
元素中添加其他界面元素,例如按鈕、文本框等,來構建應用程式的用戶界面。同樣,可以在XAML中設置屬性來更改元素的外觀和行為。
2.property和attribute
先不說WPF中兩個屬性的定義,我們先看看對應一個類的對象。
1)屬性是指類體里用get或set封裝好的屬性。屬性是面向對象的理論範疇。比如說一個盒子,盒子的高度,長度,都是這個盒子的屬性。在C#中實現的時候可以通過GET SET 封裝。
2)特性是指應用於類,欄位,方法,介面的進一步說明,用專業的術語就是給類,欄位,方法,介面補充元數據,說的再白一點就是給它們打上標記,打了標記後編譯器就知道如何來編譯它。特性是屬於編程語言層面的東西。比如2個相同的類,為了表示這2個類不完全相同或者有差異。這時候就要針對這兩個類加一些特性。
[Serializable] // 這是Attribute,打上該標記的類說明可以被序列化
class Order
{
protected internal Single Price { get; set; } // 這是Property
[Obsolete("此方法已過時,請改用xxx.")] // 打上該標記說明此方法是過時的
public Single GetPrice()
{
return default(Single);
}
}
在看在XAML中:
Attribute 在XAML中的對於標簽的屬性特征,以下都是Window標簽下的attribute
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:AvaloniaMarkdown.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaMarkdown.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
xmlns:md="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
Icon="/Assets/avalonia-logo.ico"
Title="AvaloniaMarkdown"
Property 在後臺代碼中針對對象的屬性特征,對應的後端類的對象Text,就是一個 property:
private string _text="hello";
public string Text
{
get => _text;
set => this.RaiseAndSetIfChanged(ref _text, value);
}
private string _filePath;
3.xmlns 名稱空間
xmlns[:可選的映射首碼]="名稱空間"
用於引用外來程式集
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:AvaloniaMarkdown.ViewModels"
沒有映射首碼的是預設名稱空間,預設名稱空間只能有一個。
通過xmlns,我們可以直接使用這些CLR名稱空間中的類型
4.partial關鍵字
XAML文件對應的.xaml.cs文件中的類的聲明使用了partial關鍵字,可以把一個類拆分在多處定義,只要各部分代碼不衝突即可,由於partial機制,我們實現邏輯代碼留在.cs文件中,把UI元素相關代碼分離出去。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
2.XAML語法
1.樹形結構
<Window>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Grid.Column="0" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" >
<Button>打開</Button>
<Button>保存</Button>
<Label/>
</StackPanel>
</Grid>
<TextBox Grid.Row="1" Grid.Column="0"/>
<md:MarkdownScrollViewer Grid.Row="1"
Grid.Column="1"/>
</Grid>
</Window>
XAML UI 框架是樹狀結構,以
2.x:Name
x:Name的作用:
- 告訴XAML編譯器,帶有x:Name的標簽需要聲明一個引用變數,變數名就是x:Name的值
- 將XAML標簽對應的對象的Name屬性也設為x:Name的值,並註冊到UI樹上,方便查找
2.x:Key
在資源字典(Resource Dictionary)中使用,構成其中的元素。資源(Resource )非常重要,存放需要重覆使用的內容。
<Application.Resources>
<Color x:Key="SystemAccentColor">rgb(155, 138, 255)</Color>
<Color x:Key="SystemAccentColorDark1">rgb(155, 138, 255)</Color>
<Color x:Key="SystemAltMediumLowColor">rgb(52, 53, 65)</Color>
<Color x:Key="ApplicationPageBackgroundThemeBrush">rgb(52, 53, 65)</Color>
<Color x:Key="ControlStrokeColorDefaultBrush">rgb(94, 95, 109)</Color>
</Application.Resources>
3.控制項
1.ContentControl 單一內容控制項
只能單一元素充當其內容。
例如:Button、Label等(具體看書中列表)
2.HeaderdContentControl
除了用於顯示主體內容的區域外,控制項還具有一個顯示標題(header)的區域
例如:GroupBox、TabItem
3.ItemsControl
- 顯示列表化的數據
- 內容屬性為Items或ItemsSource
- 每種ItemsControl都對應有自己的條目容器(Item Container)
例如:ListBox、TreeView
4.Decorator
在UI 上起裝飾效果,比如可以使用Border元素為一些組織在一起的內容加個邊框
例如:Border、ViewBox
5.TextBlock和TextBox
最常用的文本控制項
- TextBlock 用於顯示文本,不能編輯
- TextBox 允許編輯內容
6.Shape
繪製圖形使用的元素
- Fill 屬性設置填充
- Stroke 屬性設置邊線
7.Panel
所有的UI佈局元素都屬於這一族
Panel元素控制佈局
包括:Canvas、Grid、StackPanel等
4.佈局
WPF的UI形成的樹形結構,我們稱之為可視化樹(Visual Tree)
控制項框架形成的樹形結構,我們稱之為邏輯樹(Logic Tree)
五種大類
- Grid 網格面板
- DockPanel 停靠面板
- StackPanel 棧面板
- WrapPanel 環繞面板
- Canvas 精准定位
下麵複習下它們的使用方法:
1.Grid
網格形式佈局
1.CloumnDefinitions
定義多少列
2.RowDefinitions
定義了多少行
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Grid.Column="0" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Classes="small" Margin="0,0,20,0" Command="{Binding UploadCommand}">打開</Button>
<Button Classes="small" Margin="0,0,20,0" Command="{Binding SaveCommand}">保存</Button>
<Label Content="{Binding FilePath}" Margin="0,0,20,0"/>
</StackPanel>
</Grid>
3.Grid長寬常用設置值
- 絕對值:double 數值後加單位尾碼
- 比例值:double數值後加一個星號(*)(如上例)
- 自動值:Auto
2.StackPanel
StackPanel可以把內部的元素在縱向或橫向上緊湊排列,形成棧式佈局
適合場合:
- 同類元素需要緊湊排列(列表或菜單)
- 移除其中的元素後能夠自動補缺的佈局或者動畫
1.屬性
常用屬性 | 數據類型 | 可選值 | 說明 |
---|---|---|---|
Orientation | Orientation | Horizontal(水平排列)\Vertical(垂直排列) | 決定內部元素是水平還是垂直排列,預設值(Vertical) |
Background | Brush | 背景色(Red/Yellow等等) | |
HorizontalAlignment | HorizontalAlignment | Center(中心)/Left(靠左)/Right(靠右)/Stretch(拉伸以填充父元素) | 決定內部元素在水平方向的對齊方式 |
VerticalAlignment | VerticalAlignment | Top(上方)/Center(中心)/Bottom(下方)/Stretch(拉伸以填充父元素) | 決定內部元素在垂直方向的對齊方式 |
3.Canvas
畫布,可以使用Left、Top、Right、 Bottom。內部元素通過離上下左右的距離控制元素在佈局中的位置。
4.DockPanel
DockPanel會對每個子元素進行排序,並停靠在面板的一側,多個停靠在同側的元素則按順序排序,。
<Grid>
<DockPanel Width="Auto" Height="Auto">
<Button DockPanel.Dock="Left" >1</Button>
<Button DockPanel.Dock="Top">2</Button>
<Button DockPanel.Dock="Right">3</Button>
<Button DockPanel.Dock="Bottom">4</Button>
</DockPanel>
</Grid>
5.WrapPanel
流式佈局,根據
Orientation
屬性來設置其水平或垂直佈局方向
預設是水平排列
<WrapPanel>
<Button />
<Button />
<Button />
<Button />
<Button />
<Button />
</WrapPanel>
垂直排列
<WrapPanel Orientation="Vertical">
</WrapPanel>
5.Binding 綁定
數據交互核心屬性,在欄位定義的set語句中使用一個PropertyChanged事件,,當為Binding設置了數據源後,就會自動偵聽PropertyChanged事件
WPF
using CommunityToolkit.Mvvm
private string _searchKeyword;
public string SearchKeyword
{
get => _searchKeyword;
set => SetProperty(ref _searchKeyword, value);
}
Avalonia
using ReactiveUI;
private string _filePath;
public string FilePath
{
get => _filePath;
set => this.RaiseAndSetIfChanged(ref _filePath, value);
}
6.Dependency Property 依賴屬性
依賴屬性是一種本身沒有可以沒有值,能通過使用Binding從數據源獲取值的屬性。擁有依賴屬性的對象稱為“依賴對象”。
特點包括:
- 節省實例對記憶體的開銷
- 屬性值可以通過Binding依賴在其他的對象上
7.Attached Property 附加屬性
附加屬性,被環境賦予的屬性,作用是將屬性與數據類型(宿主)解耦,讓數據類型的設計更加靈活
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Grid.Column="0" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" >
<Button>打開</Button>
<Button>保存</Button>
<Label/>
</StackPanel>
</Grid>
<TextBox Grid.Row="1" Grid.Column="0"/>
<md:MarkdownScrollViewer Grid.Row="1"
Grid.Column="1"/>
</Grid>
上面 TextBox 的Grid.Row,Grid.Column都是附加屬性。
8.Route 和Event 路由事件
路由事件被激發後是沿著Visual Tree傳遞的,只有這樣,“藏”在Templete里的控制項才能把消息送出來。
9.Resource 資源
每個WPF的界面的元素都具有一個名為Resources的屬性,這個屬性繼承自FrameWorkElement類,其類型為ResourceDictionary,用來存儲資源。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="/Assets/Lang/en-US.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
在使用資源時候分為靜態資源(StaticResource)和動態資源(DynamicResource)
1.StaticResource
在程式載入記憶體時對資源一次性使用,之後就不再去訪問這個資源了
<TextBox Grid.Row="4"
Name="Editor3"
AcceptsReturn="True"
Text="{Binding Source={StaticResource VMLocator}, Path=EditorViewModel.Editor3Text,Mode=TwoWay}"
FontSize="{Binding Source={StaticResource VMLocator}, Path=EditorViewModel.EditorCommonFontSize}" />
2.StaticResource
程式運行過程中仍然會去訪問資源
<Rectangle Name="PART_BottomRightCorner"
Fill="{DynamicResource DataGridScrollBarsSeparatorBackground}"
Grid.Column="2"
Grid.Row="2" />
10.Template 模板
1.ControlTemplate 控制器模板
<ControlTemplate>
<Border Name="DataGridBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto,*,Auto,Auto">
<DataGridColumnHeader Name="PART_TopLeftCornerHeader"
Theme="{StaticResource DataGridTopLeftColumnHeader}" />
<DataGridColumnHeadersPresenter Name="PART_ColumnHeadersPresenter"
Grid.Column="1"
Grid.Row="0" Grid.ColumnSpan="2" />
<Rectangle Name="PART_ColumnHeadersAndRowsSeparator"
Grid.Row="0" Grid.ColumnSpan="3" Grid.Column="0"
VerticalAlignment="Bottom"
Height="1"
Fill="{DynamicResource DataGridGridLinesBrush}" />
<DataGridRowsPresenter Name="PART_RowsPresenter"
Grid.Row="1"
Grid.RowSpan="2"
Grid.ColumnSpan="3" Grid.Column="0">
<DataGridRowsPresenter.GestureRecognizers>
<ScrollGestureRecognizer CanHorizontallyScroll="True" CanVerticallyScroll="True" />
</DataGridRowsPresenter.GestureRecognizers>
</DataGridRowsPresenter>
<Rectangle Name="PART_BottomRightCorner"
Fill="{DynamicResource DataGridScrollBarsSeparatorBackground}"
Grid.Column="2"
Grid.Row="2" />
<Image Source="/Assets/maskGrad.png"
Grid.Row="1" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="4"
VerticalAlignment="Stretch"
HorizontalAlignment="Right"
Width="60"
Stretch="Fill"
IsHitTestVisible="False"
ZIndex="1" />
<ScrollBar Name="PART_VerticalScrollbar"
Orientation="Vertical"
Grid.Column="2"
Grid.Row="1"
Width="{DynamicResource ScrollBarSize}"
ZIndex="2" />
<Grid Grid.Column="1"
Grid.Row="2"
ColumnDefinitions="Auto,*">
<Rectangle Name="PART_FrozenColumnScrollBarSpacer" />
<ScrollBar Name="PART_HorizontalScrollbar"
Grid.Column="1"
Orientation="Horizontal"
Height="{DynamicResource ScrollBarSize}" />
</Grid>
<Border Name="PART_DisabledVisualElement"
Grid.ColumnSpan="3" Grid.Column="0"
Grid.Row="0" Grid.RowSpan="4"
IsHitTestVisible="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
CornerRadius="2"
Background="{DynamicResource DataGridDisabledVisualElementBackground}"
IsVisible="{Binding !$parent[DataGrid].IsEnabled}" />
</Grid>
</Border>
</ControlTemplate>
2.DataTemplate 數據模板
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
11.Style 風格
設計外觀和行為動作
1.Setter 設置器
Setter 類的Property屬性用來指明你想為目標的哪個屬性賦值,Value屬性則是你提供的屬性值
<Style Selector="Grid Button">
<Setter Property="BorderBrush" Value="rgb(94, 95, 109)" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Padding" Value="10,0,10,2" />
<Setter Property="Height" Value="32" />
<Setter Property="CornerRadius" Value="6" />
<Setter Property="Margin" Value="0" />
<Setter Property="FontFamily" Value="avares://TmCGPTD/Assets/Lato-Regular.ttf#Lato" />
<Setter Property="Transitions">
<Transitions>
<BrushTransition Property="Background" Duration="0:0:0.2" />
</Transitions>
</Setter>
</Style>
上面的例子是針對 Grid Button的Style,使用了若幹個Setter 來設置 Grid 中的Button的一些屬性,這樣,在程式中, Grid 中的Button就會具有統一的風格。
2.Trigger 觸發器
當條件滿足時會觸發一個行為。
<Grid>
<TextBlock Text="raokun" Width="75" Height="20">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="blue" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
上面的例子,是當滑鼠移動在上面時,字體的顏色變成藍色。