WPF復習知識點記錄

WPF復習知識點記錄
由于近幾年主要在做Web項目,客戶端的項目主要是以維護為主,感覺對于基礎知識的掌握沒有那么牢靠,趁著這個周末重新復習下WPF的相關(guān)知識。
文章內(nèi)容主要來自大佬劉鐵錳老師的經(jīng)典著作《深入淺出WPF》。
因為是復習,所以知識內(nèi)容不會一一記錄,如有需要了解更多可以看書中內(nèi)容。
注意:博客中的代碼示例我是以avalonia為UI框架寫的。代碼可能部分跟WPF的稍有不同。
1.從零起步認識XAML
1.什么是XAML
XAML(讀作zaml)是WPF技術(shù)中專門用于設計UI 的語言
2.優(yōu)點
實現(xiàn)界面與代碼的分離
可以設計出專業(yè)的UI和動畫
基于XML的標記語言,簡單易懂,結(jié)構(gòu)清晰
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
元素,它是一個空的容器??梢栽?code>Window元素中添加其他界面元素,例如按鈕、文本框等,來構(gòu)建應用程序的用戶界面。同樣,可以在XAML中設置屬性來更改元素的外觀和行為。
2.property和attribute
先不說WPF中兩個屬性的定義,我們先看看對應一個類的對象。
1)屬性是指類體里用get或set封裝好的屬性。屬性是面向?qū)ο蟮睦碚摲懂?。比如說一個盒子,盒子的高度,長度,都是這個盒子的屬性。在C#中實現(xiàn)的時候可以通過GET SET 封裝。
2)特性是指應用于類,字段,方法,接口的進一步說明,用專業(yè)的術(shù)語就是給類,字段,方法,接口補充元數(shù)據(jù),說的再白一點就是給它們打上標記,打了標記后編譯器就知道如何來編譯它。特性是屬于編程語言層面的東西。比如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關(guān)鍵字
XAML文件對應的.xaml.cs文件中的類的聲明使用了partial關(guān)鍵字,可以把一個類拆分在多處定義,只要各部分代碼不沖突即可,由于partial機制,我們實現(xiàn)邏輯代碼留在.cs文件中,把UI元素相關(guān)代碼分離出去。
public partial class MainWindow : Window
{
? ?public MainWindow()
? ?{
? ? ? ?InitializeComponent();
? ?}
}
2.XAML語法
1.樹形結(jié)構(gòu)
<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 框架是樹狀結(jié)構(gòu),以對象為根節(jié)點,一層一層往下包含。我們經(jīng)常需要在這棵樹上進行按名稱查找元素、獲取父子節(jié)點等操作。WPF使用VisualTreeHelper、LogicalTreeHelper來操作樹。
2.x:Name
x:Name的作用:
告訴XAML編譯器,帶有x:Name的標簽需要聲明一個引用變量,變量名就是x:Name的值
將XAML標簽對應的對象的Name屬性也設為x:Name的值,并注冊到UI樹上,方便查找
2.x:Key
在資源字典(Resource Dictionary)中使用,構(gòu)成其中的元素。資源(Resource )非常重要,存放需要重復使用的內(nèi)容。
<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 單一內(nèi)容控件
只能單一元素充當其內(nèi)容。
例如:Button、Label等(具體看書中列表)
2.HeaderdContentControl
除了用于顯示主體內(nèi)容的區(qū)域外,控件還具有一個顯示標題(header)的區(qū)域
例如:GroupBox、TabItem
3.ItemsControl
顯示列表化的數(shù)據(jù)
內(nèi)容屬性為Items或ItemsSource
每種ItemsControl都對應有自己的條目容器(Item Container)
例如:ListBox、TreeView
4.Decorator
在UI 上起裝飾效果,比如可以使用Border元素為一些組織在一起的內(nèi)容加個邊框
例如:Border、ViewBox
5.TextBlock和TextBox
最常用的文本控件
TextBlock 用于顯示文本,不能編輯
TextBox 允許編輯內(nèi)容
6.Shape
繪制圖形使用的元素
Fill 屬性設置填充
Stroke 屬性設置邊線
7.Panel
所有的UI布局元素都屬于這一族
Panel元素控制布局
包括:Canvas、Grid、StackPanel等
4.布局
WPF的UI形成的樹形結(jié)構(gòu),我們稱之為可視化樹(Visual Tree)
控件框架形成的樹形結(jié)構(gòu),我們稱之為邏輯樹(Logic Tree)
五種大類
Grid 網(wǎng)格面板
DockPanel ??棵姘?/p>
StackPanel 棧面板
WrapPanel 環(huán)繞面板
Canvas 精準定位
下面復習下它們的使用方法:
1.Grid
網(wǎng)格形式布局
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 數(shù)值后加單位后綴
比例值:double數(shù)值后加一個星號(*)(如上例)
自動值:Auto
2.StackPanel
StackPanel可以把內(nèi)部的元素在縱向或橫向上緊湊排列,形成棧式布局
適合場合:
同類元素需要緊湊排列(列表或菜單)
移除其中的元素后能夠自動補缺的布局或者動畫
1.屬性
常用屬性數(shù)據(jù)類型可選值說明OrientationOrientationHorizontal(水平排列)\Vertical(垂直排列)決定內(nèi)部元素是水平還是垂直排列,默認值(Vertical)BackgroundBrush背景色(Red/Yellow等等)HorizontalAlignmentHorizontalAlignmentCenter(中心)/Left(靠左)/Right(靠右)/Stretch(拉伸以填充父元素)決定內(nèi)部元素在水平方向的對齊方式VerticalAlignmentVerticalAlignmentTop(上方)/Center(中心)/Bottom(下方)/Stretch(拉伸以填充父元素)決定內(nèi)部元素在垂直方向的對齊方式
3.Canvas
畫布,可以使用Left、Top、Right、 Bottom。內(nèi)部元素通過離上下左右的距離控制元素在布局中的位置。
4.DockPanel
DockPanel會對每個子元素進行排序,并停靠在面板的一側(cè),多個停靠在同側(cè)的元素則按順序排序,。
<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
流式布局,根據(jù)
Orientation
屬性來設置其水平或垂直布局方向
默認是水平排列
<WrapPanel>
? ?<Button />
? ?<Button />
? ?<Button />
? ?<Button />
? ?<Button />
? ?<Button />
</WrapPanel>
垂直排列
<WrapPanel Orientation="Vertical">
</WrapPanel>
5.Binding 綁定
數(shù)據(jù)交互核心屬性,在字段定義的set語句中使用一個PropertyChanged事件,,當為Binding設置了數(shù)據(jù)源后,就會自動偵聽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從數(shù)據(jù)源獲取值的屬性。擁有依賴屬性的對象稱為“依賴對象”。
特點包括:
節(jié)省實例對內(nèi)存的開銷
屬性值可以通過Binding依賴在其他的對象上
7.Attached Property 附加屬性
附加屬性,被環(huán)境賦予的屬性,作用是將屬性與數(shù)據(jù)類型(宿主)解耦,讓數(shù)據(jù)類型的設計更加靈活
<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 路由事件
路由事件被激發(fā)后是沿著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>
在使用資源時候分為靜態(tài)資源(StaticResource)和動態(tài)資源(DynamicResource)
1.StaticResource
在程序載入內(nèi)存時對資源一次性使用,之后就不再去訪問這個資源了
<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 數(shù)據(jù)模板
<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就會具有統(tǒng)一的風格。
2.Trigger 觸發(fā)器
當條件滿足時會觸發(fā)一個行為。
<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>
上面的例子,是當鼠標移動在上面時,字體的顏色變成藍色。