WPF學習筆記(一)

引言

在桌面開發領域,雖然在某些領域,基於electron的跨平臺方案可以爲咱們帶來某些便利,可是因爲WPF技術可以更好的運用Direct3D帶來的性能提高、以及海量Windows操做系統和硬件資源的支持,因此他依然有着得天獨厚的優點。前端

固然,選用一門技術,依然看公司的基因土壤和綜合因素或者老闆的心血來潮,例如QT也一樣是一門很是不錯的跨平臺圖形界面解決方案。git

目前咱們公司在桌面開發領域普遍應用了WPF技術,主要是使用其做爲大屏數據可視化相關的UI呈現,包括一些數據展現效果、動畫效果等。因爲以前我對WPF僅有三週經驗,所以在開發和設計相關功能時,一些簡單功能還能勉強完成,稍微複雜一點的就有點費時過長了,所以這篇文章主要梳理本身的學習筆記,以便總結學習成果。github

如何學習WPF技術?

在Quote上有人提出了這樣一個相同的問題,查看問題,開發者Srikanth Pagadala如是回答:web

一、以瞭解基礎控件做爲學習的起步過程:這些控件包括TextBox,Button,TextBlock及其餘的,理解這些控件對外提供的屬性,以及如何使用。
二、瞭解和使用佈局空間:例如Grid、StackPanel、DockerPanel和其餘控件,在這一點上,你須要花費大量的時間。同時你須要學會建立複雜的UI設計。
三、瞭解循環類型的空間,例如ItemControl控件。
四、瞭解關於模板的概念。包括如何定義包含CheckBox的Combox,同時這個控件還包含了一張圖片的按鈕,以及如何在ItemsControl中使用不一樣的模板。
五、理解數據綁定的運行機制。嘗試建立一個MVVM或相似類型的應用程序。
六、建立一個典型的控件,探索DependencyProperties(依賴屬性)和AttachedProperties(附加屬性)。
七、建立一個樣式資源,理解如何給控件設計樣式。windows

除此以外,還有其餘開發者給出了補充回答:後端

一、學習控件的數據綁定過程,在DataGrid上實現數據綁定。
二、學習和實現INotifyPropertyChanged類。查看如何實現
三、學習Observable Collection。該類型的集合普遍使用於數據集合綁定方面,同時也提供了數據改變通知的機制。
四、使網格上的列可編輯。用文本控件(用戶項目模板)替換列。爲每一個捕獲文本更改事件的列建立一個屬性。在文本控件上使用綁定類型。嘗試捕獲您在後端在網格上所作的更改。
五、成功將數據控件中的文本控件與後端屬性綁定後,請在同一頁面上建立網格的副本。嘗試同步這兩個網格。例如,您在第一個網格中所作的每一個更改都必須在第二個網格中自動更新。api

網站「https://www.wpf-tutorial.com/」是一個專門用於學習WPF的網站,經過這個網站,能夠快速的入門WPF。數組

因爲WPF技術已經比較熟悉,因此書籍也比較多,網友推薦來自劉鐵猛老師的《深刻淺出WPF》這本書,而我經過Kindle則看到了一本比較有意思的書《葵花寶典-WPF自學手冊》,這本書寫得比較生動,經過故事的形式講了WPF的許多技術原理,無形中讓我對WPF的概念有了許多新的認識。固然,這本書已經有點年頭了。瀏覽器

WPF的經常使用控件

控件類型 控件名稱 控件說明 連接地址
組件 Window 窗口 查看示例
Page 頁面 查看示例
NavigationWindow 導航窗口 查看示例
Frame 查看示例
常規控件 Button 按鈕控件,提供Content做爲內容 查看示例
TextBox 文本框控件,用以輸入文本 查看示例
TextBlock 文本塊,用以顯示文本 查看示例
Label 標籤,用以顯示文本 查看示例
ProgressBar 進度條 查看示例
ToggleButton 一種能夠設置開關三態的按鈕 查看示例
Image 圖像控件,經過Source設置資源路徑 查看示例
CheckBox 勾選框,能夠設置是否勾選的三種狀態 查看示例
RichTextBox 富文本框,能夠多種格式顯示和輸入文本 查看示例
TreeView 樹視圖,以樹狀圖的形式顯示綁定內容,能夠顯示是否勾選三態。 查看示例
WebBrowser 瀏覽器,基於IE內核的瀏覽器控件 查看示例
Calendar 日曆控件 查看示例
ComboBox 下拉列表 查看示例
ContentControl 內容控件 查看示例
Expander 擴展器,能夠顯示和摺疊面板內的元素 查看示例
GroupBox 分組框 查看示例
StatusBar 狀態欄,用於在頁面下方顯示狀態信息。 查看示例
DateTimePicker 時間控件,能夠設置時間狀態。 查看示例
DocumentViewer 文檔查看器 查看示例
RadioButton 單選按鈕 查看示例
ScollViewer 滾動視圖 查看示例
ScollBar 滾動條 查看示例
Separator 分隔器 查看示例
ToolBar 工具條 查看示例
Slider 查看示例
Menu 菜單 查看示例
MediaElement 多媒體控件 查看示例
PasswordBox 密碼輸入框 查看示例
TabControl 選項卡 查看示例
ToolBarTray 工具條 查看示例
WindowsFormsHost 用以承載WinForm 查看示例
Border 邊框 查看示例
數據控件 ListView 列表視圖 查看示例
DataGrid 數據表 查看示例
ListBox 列表框 查看示例
佈局 WrapPanel 可變面板 查看示例
StackPanel 固定面板 查看示例
DockerPanel 停靠面板 查看示例
Grid 表格佈局 查看示例
UniformGrid 統一分佈表格佈局 查看示例
查看示例 Canvas 畫布 查看示例
圖形 Point 查看示例
Line 查看示例
Path 路徑 查看示例
Polygon 多邊形 查看示例
Polyline 多段線 查看示例
Rectangle 矩形 查看示例
Shape 畫筆 查看示例
Rectangle 矩形 查看示例
Ellipse 橢圓 查看示例

WPF的XAML語法

概述

在WPF技術中引入的XAML語法算是該技術的一大特點,也是被學習者視同爲學習路徑陡峭的「罪魁禍首」。緣由是在前端技術飛速發展的今天,HTML的語法體系因爲更早的被開發者接受,因此也天然而然更容易成爲開發者的首選。electron

而XAML是一種脫胎於XML,並吸取了HTML的精華的語法體系,是一種界面描述語言,XML語法自己相對而言較爲臃腫的體系,看似成爲了他的歷史負擔,可是其實倒也沒那麼複雜,經過幾個簡單的示例,其實就足夠掌握這門新的語法體系了。例如,使用這樣的語法,徹底能夠平滑過渡到這樣的語法體系。(部分標籤其實只是大小寫不一樣)。固然,在XAML中熟練編寫樣式,確實須要花一點點時間。

在WPF中,經過XAML定義面向用戶交互層的界面,而後編譯成baml運行,後端則使用C#或VB.NET這樣的CLR語法來實現邏輯交互。

XAML的語法定義

XAML的根元素定義

根元素定義是定義XAML的命名空間。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

XAML的屬性語法

經過xaml定義按鈕,並設置文本爲 helloworld 。這種寫法在官方文檔中稱爲「屬性語法」,即直接在XAML中對屬性進行設置。

<Button Background="Blue" Foreground="Red" Content="hello world"/>

XAML的屬性元素語法

經過xaml定義按鈕,並設置其背景爲藍色畫筆,字體顏色爲紅色畫筆,內容 爲helloworld。這種寫法在官方文檔中稱爲「屬性元素語法」。

<Button>
  <Button.Background>
    <SolidColorBrush Color="Blue"/>
  </Button.Background>
  <Button.Foreground>
    <SolidColorBrush Color="Red"/>
  </Button.Foreground>
  <Button.Content>
    hello world
  </Button.Content>
</Button>

XAML的集合語法

定義按鈕的顏色爲紅色和藍色漸變色,內容爲helloworld。這種稱爲「集合語法」。

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
    <GradientStop Offset="0.0" Color="Red" />
    <GradientStop Offset="1.0" Color="Blue" />
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

XAML的樣式定義

經過屬性語法來定義按鈕的外觀

樣式定義使用 標籤,而後在中間對樣式的內容進行定義。

例如,如下表示經過XAML語法對 ToggleButton 按鈕定義了一個命名爲 ToggleLikeButtonStyle 的樣式。

 <Style TargetType="ToggleButton" x:Key="ToggleLikeButtonStyle">
            <Setter Property="Margin"   Value="4" />

            <Setter Property="FontWeight" Value="Black"/>

            <Setter Property="Foreground"  Value="Black" />

            <Setter Property="BorderThickness" Value="0"/>

            <Setter Property="IsThreeState" Value="False"></Setter>

</Style>

WPF中的模板Template

WPF中的控件能夠經過模板 Template 的形式來定義其內容,使得開發者可以經過 XAML 靈活的對控件的外觀進行擴展。例如,以下定義了一個 Template,這個控件模板將會對控件(Button)定義填充制定顏色。

 <Setter Property="Template">  
                <Setter.Value>  
                    <ControlTemplate>  
                        <Border BorderThickness="0" CornerRadius="3">  
                            <Border.Background>  
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">  
                                    <GradientStop Color="#4696F2" Offset="0.5"/>  
                                </LinearGradientBrush>  
                            </Border.Background>  
                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />  
                        </Border>  
                    </ControlTemplate>  
                </Setter.Value>  
            </Setter>

XAML中的觸發器Triggers

傳統的WinForm開發者習慣於經過事件的機制對按鈕的外觀進行定義,而在WPF中,則能夠經過屬性的形式對外觀進行設置,這使得開發者更可以寫出高質量的代碼。

例如,以下代碼經過定義觸發器,設置控件(控件爲 ToggleButton),當控件的勾選狀態屬性爲「IsChecked」 時,其邊框填充色爲#4696F2顏色。

<ControlTemplate.Triggers>  
                            <Trigger Property="IsChecked" Value="True">  
  <Setter Property="Border.Background" TargetName="PART_Background"
<Setter.Value>
                                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                            <GradientStop Color="#4696F2" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="Width" TargetName="PART_Background" Value="60"></Setter>
                                <Setter Property="Content"  TargetName="contextPresenter" Value="已點贊"></Setter>
                                <Setter Property="Visibility"  TargetName="contextPresenter" Value="Visible"></Setter>
                                <Setter Property="Visibility" TargetName="contextImage" Value="Hidden"/>
                            </Trigger>
</ControlTemplate.Triggers>                         
                                   

部分完整代碼

在上述事例中,共定義了兩個按鈕的樣式,分別是:

  • FlatButtonStyle,這是個圓角按鈕。
<Style TargetType="Button" x:Key="FlatButtonStyle">
            <Setter Property="Margin"   Value="4" />
            <Setter Property="FontWeight" Value="Black"/>
            <Setter Property="Foreground"  Value="Black" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Border BorderThickness="0" CornerRadius="3">
                            <Border.Background>
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                    <GradientStop Color="#4696F2" Offset="0.5"/>
                                </LinearGradientBrush>
                            </Border.Background>
                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
  • ToggleLikeButtonStyle,這是一個點贊按鈕。
<Style TargetType="ToggleButton" x:Key="ToggleLikeButtonStyle">
            <Setter Property="Margin"   Value="4" />
            <Setter Property="FontWeight" Value="Black"/>
            <Setter Property="Foreground"  Value="Black" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="IsThreeState" Value="False"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border BorderThickness="0" CornerRadius="3" Name="PART_Background">
                            <Border.Background>
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                    <GradientStop Color="#525252" Offset="0.5"/>
                                </LinearGradientBrush>
                            </Border.Background>
                            <Grid>
                                <ContentPresenter x:Name="contextPresenter" Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                <Image x:Name="contextImage" Width="24" Height="24" Source="assests/thumbs-up-outline.png" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Border.Background" TargetName="PART_Background">
                                    <Setter.Value>
                                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                            <GradientStop Color="#4696F2" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="Width" TargetName="PART_Background" Value="60"></Setter>
                                <Setter Property="Content"  TargetName="contextPresenter" Value="已點贊"></Setter>
                                <Setter Property="Visibility"  TargetName="contextPresenter" Value="Visible"></Setter>
                                <Setter Property="Visibility" TargetName="contextImage" Value="Hidden"/>
                            </Trigger>
                            <Trigger Property="IsChecked" Value="False">
                                <Setter Property="Border.Background" TargetName="PART_Background">
                                    <Setter.Value>
                                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                            <GradientStop Color="#525252" Offset="0.5"/>
                                        </LinearGradientBrush>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="Width" TargetName="PART_Background" Value="40"></Setter>
                                <Setter Property="Visibility"  TargetName="contextPresenter" Value="Hidden"></Setter>
                                <Setter Property="Visibility" TargetName="contextImage" Value="Visible"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
</Style>

XAML的標記擴展

經過了解WPF的經常使用控件,咱們能夠知道本身須要使用的控件有哪些屬性,並能使用 XAML 語法對相應的屬性進行設置,這種設置方法有別於經過C#代碼的形式進行定義的方法,在 XAML中的屬性稱爲 「標記」。標記使用 「{}」 花括號,編譯器經過該花括號將語法和XAML語法進行區分。

例如:

 HeaderTemplate="{DynamicResource StretchedHeaderTemplate}"

標記值的轉換與TypeConverters

在進行標記值轉換時,有時候須要使用TypeConverters實現類型轉換。例如,在上述示例代碼中,能夠看到使用了字符串「#525252」來定義顏色,在內部就是實現了從字符串到 Color 類的轉換過程。限於篇幅有限,此處就暫時略過。

XAML中內置特殊標記擴展

  • x:Type:特定類型
<object property="{x:Type prefix:typeNameValue}" .../>
  • x:Static:使用靜態值。
<object property="{x:Static prefix:typeName.staticMemberName}" .../>
  • x:Null:使用空對象定義爲屬性值。
<object property="{x:Null}" .../>
  • x:Array:使用數組對象。
<x:Array Type="typeName">    
  arrayContents    
</x:Array>

常見的標記擴展

  1. StaticResource:經過替換已定義資源的值來爲屬性提供內容,該資源標記在XAML加載時自動執行。靜態資源沒法經過在XAML語法體系中對其引用關係進行前向引用,意味着沒法經過多層級關係定義可複用的樣式資源,若是須要這樣作,則須要使用DynamicResource。
<object property="{StaticResource key}" .../>
  1. DynamicResource:在運行時爲資源提供內容。
<object property="{DynamicResource key}" .../>
  1. Binding:在運行時爲使用數據上下文爲數據提供內容。
<object property="{Binding}" .../>    
-or-  
<object property="{Binding  bindProp1=value1[, bindPropN=valueN]*}" ...  
/>    
-or-    
<object property="{Binding path}" .../>  
-or     
<object property="{Binding path[, bindPropN=valueN]*}" .../>
  1. RelativeSource:提供了可在運行時對象樹中導航幾個可能的關係的 Binding 的源信息。
<Binding RelativeSource="{RelativeSource modeEnumValue}" .../>
  1. TemplateBinding:使控件模板可以使用模板化屬性的值,這些屬性來自於將使用該模板的類的對象模型定義屬性。
<object property="{TemplateBinding sourceProperty}" .../>
  1. ColorConvertedBitmap:提供一種方法,用於指定沒有嵌入的配置文件的位圖源。 顏色上下文/配置文件由 URI 指定,與映像源 URI 相同。
<object property="{ColorConvertedBitmap imageSource sourceIIC destinationIIC}" .../>
  1. ComponentResourceKey和TemplateResourceKey:
<object x:Key="{ComponentResourceKey {x:Type targetTypeName}, targetID}" .../>

XAML資源複用

在開發過程當中,咱們能夠直接在按鈕上進行按鈕模板的定義,例以下面的代碼。

<Button Width="40" Height="40" Style="{DynamicResource CubeImageButtonStyle}" Click="Button_Click" Content="點贊">
    <Button.Background>
                                <ImageBrush ImageSource="/assests/favicon.png" Stretch="Fill"/> 
                            </Button.Background>
                        </Button>   
                          <Setter Property="Template"
                <Setter.Value>
                    <ControlTemplate>
                        <Border BorderThickness="0" CornerRadius="3">
                            <Border.Background>
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                    <GradientStop Color="#4696F2" Offset="0.5"/>
                                </LinearGradientBrush>
                            </Border.Background>
                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 </Window.Resources>
 <Grid>
<Button Grid.Column="0" Grid.Row="1" Style="{StaticResource FlatButtonStyle}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="48" Height="16" FontSize="10" Background="#4696F2" Content="獲取"></Button>
 </Grid>
                       

這樣的代碼在界面比較簡單時,還無所謂,可是隨着控件的樣式愈來愈複雜,可能會成爲一團亂麻,這對於追求優雅代碼的咱們來講,多是難以忍受的,因此每每會使用資源引用來完成。

StaticResource

例如,咱們能夠在當前頁面代碼中定義對應的樣式,這種樣式可使用 StaticResource 的形式引入。可是這樣的引用形式,沒有對象圖的訪問權限,意味着沒法訪問資源依賴的其餘資源。

 <Window.Resources>  
<Style TargetType="Button" x:Key="FlatButtonStyle">     
            <Setter Property="Margin"   Value="4" />    
            <Setter Property="FontWeight" Value="Black"/>    
            <Setter Property="Foreground"  Value="Black" />        
            <Setter Property="BorderThickness" Value="0"/>    
</Window.Resources>         

DynamicResource

將上述代碼中的{StaticResource FlatButtonStyle} 改爲{StaticResource FlatButtonStyle}則會在運行時加載樣式,並能夠訪問相應的對象圖。

固然,這樣的更改意義不大,若是該FlatButtonStyle引用了其餘樣式或元素,會發生做用。

<Grid
<Button Grid.Column="0" Grid.Row="1" Style="{StaticResource FlatButtonStyle}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="48" Height="16" FontSize="10" Background="#4696F2" Content="獲取"></Button>
 </Grid>

注意事項

一、因爲XAML語法脫胎於XML語法,而XML語法中自己對某些輸入字符,如「<>」存在限制,因此在XAML中也會出現這類問題,並會被Visual Studio檢測出錯誤而沒法編譯,須要使用UTF-8編碼進行轉換。

用戶控件和自定義控件

用戶控件

而用戶控件,使用於控件組合的場景。

自定義控件

在筆者進行開發時,老是思考到底是使用用戶控件,仍是自定義控件,後來在閱讀《葵花寶典-WPF自學手冊》這本書中,終於得以大徹大悟。

做者指出:「不要被控件的外觀所欺騙,要考慮其內在本質」。即思考控件的基本特徵,首先想到該控件的行爲與原有控件的行爲是否類似,若是可以找到,則修改原有控件,而不是定義一個控件。尤爲是在XAML語法中,可以經過Content 模型和模板、附加屬性的運用,使得自定義控件的用途獲得了進一步縮減,只有當實在萬不得已時,在定義自定義控件。

做者給出了使用自定義控件的分析思路:

例如,在示例代碼ToggleLikeButtonStyle 中,我實現了一個點贊和取消點讚的狀態,則使用了ToggleButton來完成,就不必使用 Button 擴展出一個是否點讚的狀態了。

而若是咱們須要實現的功能有這麼複雜,那大概使用傳統的控件就沒法實現,就得使用自定義控件了。(點擊查看示例代碼

做者定義了自定義控件 ButtonEx,並實現了依賴屬性 ButtonType,見【依賴屬性】,並定義了不一樣類型的樣式特徵。

 <Trigger Property="ButtonType" Value="Icon">
                <Setter Property="Cursor" Value="Hand"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type controls:ButtonEx}">
                            <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                                <Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{TemplateBinding Icon}" Stretch="None"/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Opacity" Value="0.8"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Opacity" Value="0.9"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>

使用時,只需這樣設置,便可實現不一樣類型的按鈕外觀。

 <controls:ButtonEx Icon="/Images/search.png"  Margin="10" ButtonType="Icon"/>

屬性和事件

依賴屬性

依賴屬性是爲既有WPF控件對象定義自定義屬性,以便支持其擴展,例如在上述自定義控件的示例中,就定義了依賴屬性 ButtonType,實現了不一樣類型的按鈕外觀。

public ButtonType ButtonType  
        {
            get { return (ButtonType)GetValue(ButtonTypeProperty); }
            set { SetValue(ButtonTypeProperty, value); }
        }


        public static readonly DependencyProperty ButtonTypeProperty =

            DependencyProperty.Register("ButtonType", typeof(ButtonType), typeof(ButtonEx), new PropertyMetadata(ButtonType.Normal));

附加屬性
按照官方的說法就是「附加屬性旨在用做可在任何對象上設置的一類全局屬性」,例如,DockPanel面板中的子對象,繼承了來自於容器對象的附加屬性,使得其可以在父對象中實現停靠的功能。

<DockPanel>
  <CheckBox DockPanel.Dock="Top">Hello</CheckBox>
</DockPanel>

路由事件

基本定義

假設咱們定義了幾個這樣的控件。

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

實現了這樣的界面

路由事件就是針對這組元素樹中多個元素調用處理程序的事件。當咱們點擊了按鈕Button時,將會觸發 Button=>StackPanel=>Border的事件路由,而不是像WinForm應用同樣,只能觸發最上層的Button的按鈕點擊事件。

路由策略

  • 冒泡事件(官方稱爲浮升,這個翻譯有點。。):調用事件源上的事件處理程序。 路由事件隨後會路由到後續的父級元素,直到到達元素樹的根。 大多數路由事件都使用浮升路由策略。 浮升路由事件一般用於報告來自不一樣控件或其餘 UI 元素的輸入或狀態變化。
  • 直接: 只有源元素自己纔有機會調用處理程序以進行響應。經過使用 EventSetter 和 EventTrigger使用來設置處理程序。例如,可使用RoutedEventArgs的Handled,設置爲 true 將事件標記爲已處理,將 "中止" 路由用於隧道路由或冒泡路由。
void MakeButton2()
{
  Button b2 = new Button();
  b2.Click += new RoutedEventHandler(Onb2Click2);
}
void Onb2Click2(object sender, RoutedEventArgs e)
{
  //logic to handle the Click event     
}
  • 隧道:最初將調用元素樹的根處的事件處理程序。 隨後,路由事件將朝着路由事件的源節點元素(即引起路由事件的元素)方向,沿路由線路傳播到後續的子元素。
  • WPF中約定,隧道路由事件的名稱以單詞「Preview」開頭。 輸入事件一般成對出現,一個是浮升事件,另外一個是隧道事件。例如,以下圖所示,假設按鈕2爲觸發事件的源。

圖片

一、處理Border根元素的隧道事件PreviewMouseDown

二、處理StackPanel面板的隧道事件PreviewMouseDown.

三、處理Button按鈕的隧道事件的PreMouseDown。

四、處理Button按鈕的MouseDown事件。

五、處理StackPanel的MouseDown事件。

六、處理Border的MouseDown事件。

總結

WPF是一個很是龐大的技術體系,以上學習路徑僅供開發者進行簡單的入門,因爲篇幅有限,對於標記擴展還須要進一步理解透徹,以及格式轉換、圖形繪製、數據綁定、MVVM等內容未能一一描述。

若是果想要對WPF進一步瞭解,最好經過系統的學習相關知識,除了前面提到的網站和幾本書,最好的入門網站依然是微軟官方文檔

相關文章
相關標籤/搜索