最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

WPF 昨日黃花?趁它黃之前入一下門吧!

2023-03-01 02:58 作者:緊果唄  | 我要投稿

# =?? WPF Application Startup

Your Codes are Not Your Codes

GIF 動(dòng)畫制作工具包括 screen-capture-recorder 與 ffmpeg:

ffmpeg -y -f dshow -i audio="virtual-audio-capturer":video="screen-capture-recorder" -offset_x 0 -offset_y 0 -video_size 1920x1080 yo.mp4

?ffmpeg -ss 49 -to 56 -i .\yo.mp4 -r 5 you.gif

這里以下面兩條命令創(chuàng)建的 WPF 和 WinForms 模板程序開始:


? ? dotnet new wpf

? ? dotnet new winforms

這兩種 Windows GUI 項(xiàng)目有相似的 csproj 配置,差別在于使用了不同開發(fā)框架和開發(fā)模式。 WPF 使用 UI 和代碼分享的開發(fā)模式,WinForms 是全代碼的舊方式。


它們屬于兩套界面渲染方式。WinForm 是傳統(tǒng) GDI 繪制方式的封裝。 WPF 是基于 DirecX 渲染的界面,也脫離了對(duì)傳統(tǒng) Windows 控件的依賴,沒(méi)有歷史包袱,理論上可以展現(xiàn)更炫酷的界面。全新 UI 描述語(yǔ)言,特別是可以通過(guò)模板的嵌套實(shí)現(xiàn)復(fù)雜的元素,通過(guò) style 實(shí)現(xiàn)類似 CSS 樣式定義的功能。通過(guò)完善的數(shù)據(jù)綁定機(jī)制實(shí)現(xiàn)業(yè)務(wù)邏輯可以專心對(duì)數(shù)據(jù)而不是界面進(jìn)行開發(fā)。數(shù)據(jù)綁定模式 MVVM 是 Web 中流行的開發(fā)模式。


XAML - Extensible Application Markup Language 是實(shí)現(xiàn) MVVM - Model View ViewModel 數(shù)據(jù)驅(qū)動(dòng)編程模式非常好的工具,這是一種能將 UI 和代碼很好地解耦的設(shè)計(jì)模式。做得較好的 MVVM 框架,比如 React/Angular/Vue 都是大量用戶在使用,可見這是多么成功的編程模式。


目前,WPF、 UWP、 Xamarin 等一眾框架都基于 XAML 技術(shù),Xamarin.Forms 4.1+ 支持熱重載 XAML Hot Reload,需要 Visual Studio 2019 支持,但是不能執(zhí)重載事件處理關(guān)系的更改。

https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/media/wpf-architect1.png


Winform 本質(zhì)上就是在 MFC 上增加一層 .Net API。2006 年開始就只有幾個(gè)人在維護(hù),基本上不增加任何新功能,只是做 bug fix。WinForm 用的是 Windows 以前那一套每個(gè)控件都是一個(gè)窗口的設(shè)計(jì),而 WPF 本身只有一個(gè)窗口,Visual Tree 上繪制所有控件,它還可以有效利用 GPU。


先來(lái)認(rèn)識(shí) WPF - Windows Presentation Foundation 程序的核心,是一個(gè)與分辨率無(wú)關(guān)且基于矢量的呈現(xiàn)引擎,旨在充分利用現(xiàn)代圖形硬件。 WPF 通過(guò)一套完善的應(yīng)用程序開發(fā)功能對(duì)該核心進(jìn)行了擴(kuò)展,這些功能包括可擴(kuò)展應(yīng)用程序標(biāo)記語(yǔ)言 XAML、控件、數(shù)據(jù)綁定、布局、二維和三維圖形、動(dòng)畫、樣式、模板、文檔、媒體、文本和版式。 WPF 屬于 .NET,因此可以生成整合 .NET API 其他元素的應(yīng)用程序。


WPF 主要優(yōu)勢(shì)在動(dòng)畫和 3D 上,缺點(diǎn)也明顯,平臺(tái)局限性、不能用于舊系統(tǒng):


1. XAML 可視化設(shè)計(jì)可以讓設(shè)計(jì)師直接加入開發(fā)團(tuán)隊(duì)、降低溝通成本。

2. XAML 圖形繪制功能非常強(qiáng)大,可以輕易繪制出復(fù)雜的圖標(biāo)、圖畫。

3. WPF 支持“濾鏡”功能,可以像 Photoshop 那樣為對(duì)象添加各種效果。

4. WPF 原生支持動(dòng)面開發(fā),設(shè)計(jì)師、程序員都能夠使用 XAML 或 C# 輕松開發(fā)制作出炫麗的動(dòng)畫效果。

5. WWF 原生支持 3D 效果,甚至可以將其他 3D 建模工具創(chuàng)建的模型導(dǎo)入進(jìn)來(lái)使用。

6. Blend 作為專門的設(shè)計(jì)工具讓 WPF 如虎添翼,幫助不了解編程的設(shè)計(jì)師快速上手,建立圖形或動(dòng)畫的原型。


從 WPF 的實(shí)現(xiàn)原理上看,這個(gè)產(chǎn)品的野心是挺大的,一方面想擺脫舊有 WinForms 的各種約束,一方面又期待著能基于 DirectX 搞游戲開發(fā)。曾經(jīng)的 Silverlight 已經(jīng)成為棄子,所以,大公司的產(chǎn)品有大坑。時(shí)代變了,WPF 框架設(shè)計(jì)很好很徹底,但 Web 成為了跨平臺(tái)首選。React、Vue、Angular 哪個(gè)比不 WPF,哪個(gè)不比 WPF 香[doge]。自家還有最新的 WinUI 3 Preview。


微軟買來(lái)的 Xamarin 也似乎沒(méi)有在微軟帶領(lǐng)下發(fā)揚(yáng)光大,桌面開發(fā)領(lǐng)域,微軟背上了沉重的技術(shù)債務(wù)。


拋開以上問(wèn)題,就 WPF 本身而言,尚有值得研究?jī)?nèi)容。從以往的 UI 框架發(fā)展來(lái)看,UI 是浮云,而 XAML 這里面潛藏的數(shù)據(jù)結(jié)構(gòu)與處理技術(shù)才是一切的核心啊!


XAML 繪圖本身就是矢量的,支持各式各樣的填充和效果,還可以添加濾鏡。


XAML 矢量圖是借助 Expression Studio 中的 Design 和 Blend 兩個(gè)工具繪制。Blend 可以直接繪制 XAML 圖形;Design 可以像 Photoshop 或者 Fireworks 那樣繪制圖形,再由設(shè)計(jì)者決定導(dǎo)出 PNG 或 XAML 格式。


可以使用 Blend for Visual Studio 社區(qū)版自帶的可視化界面開發(fā)工具。簡(jiǎn)單來(lái)說(shuō),Blend 就是一個(gè)基于 XAML 數(shù)據(jù)可視化開發(fā)工具,與流行的節(jié)點(diǎn)化編程工具不同,Blend 使用的是基于數(shù)據(jù)綁定與平面設(shè)計(jì)相結(jié)合的開發(fā)模式。在設(shè)計(jì)視圖中,可以添加一些可視的圖形控件,也可以添加一些功能性 XML 節(jié)點(diǎn)。


WPF 的基本圖形派生自 System.Windows.Shapes 命名空間 Shape 基類,包括以下幾個(gè):


1. **Line**:直線段,可以設(shè)置其筆觸(Stroke)。

2. **Rectangle**:矩形,既有筆觸,又有填充(Fill)。

3. **Ellipse**:橢圓,長(zhǎng)、寬相等的橢圓即為正圓,既有筆觸又有填充。

4. **Polygon**:多邊形,由多條直線段圍成的閉合區(qū)域,既有筆觸又有填充。

5. **Polyline**:折線(不閉合),由多條首尾相接的直線段組成。

6. **Path**:路徑(閉合區(qū)域),基本圖形中功能最強(qiáng)大的一個(gè),可由若干直線、圓弧、貝塞爾曲線組成。


其中,Rectangle 和 Ellipse 是兩種可以通過(guò)資產(chǎn)面板添加到設(shè)計(jì)視圖的圖形控件。而路徑需要通過(guò) Pen 或 Pencil 工具繪制。因?yàn)?WFP 是完全基于 DirecX 繪圖的框架,可以直接使用筆畫工具在設(shè)計(jì)視圖上繪制任意的路徑曲線。


在資產(chǎn)面板上按不同的分類羅列,可以將圖形控件,或者其它功能性節(jié)點(diǎn)添加到 XAML 設(shè)計(jì)視圖中。


概括來(lái)說(shuō),Blend 提供的設(shè)計(jì)界面操作真的談不上非常好用,只能說(shuō)功能呆滯,不僅會(huì)報(bào)錯(cuò),還會(huì)卡死。甚至曲線控制點(diǎn)的平滑屬性都不能控制,需要用戶記住 SVG 繪圖指令,以備不時(shí)之需要:


- M: 表示繪制起點(diǎn),如:M 0,0

- L: 表示繪制直線 (H:橫線 V:豎線),如:L 100,0

- C: 三次方貝塞爾曲線,如:C 100,200 200,400 300,200

- Q: 二次曲線

- z: 閉合


對(duì)象與時(shí)間線面板顯示的樹狀結(jié)構(gòu)就是 Visual Tree,與 XAML 中的數(shù)據(jù)節(jié)點(diǎn)對(duì)應(yīng)。在樹狀結(jié)構(gòu)中選擇一個(gè)對(duì)象后,其屬性會(huì)在屬性面板顯示。時(shí)間線另一個(gè)功能就是用來(lái)管理動(dòng)畫資源,**Storyboard** 情節(jié)概要,是動(dòng)畫制作中使用術(shù)語(yǔ),在 XAML 中是一種動(dòng)畫資源。


動(dòng)畫的本質(zhì)是時(shí)間與變化的組合,通過(guò)記錄某一時(shí)間段下控件的屬性變化數(shù)據(jù),并且在程序執(zhí)行時(shí)回放,這就是最基本的動(dòng)畫技術(shù)。


時(shí)間線 Timeline,它所做的工作就是,將記錄到的數(shù)據(jù)以關(guān)鍵幀的形式保存起來(lái)??梢詾?WFP 窗口創(chuàng)建多個(gè) Storyboard,以記錄多個(gè)基于關(guān)鍵幀的動(dòng)畫。


動(dòng)畫即時(shí)間線,時(shí)間線即動(dòng)畫。所有動(dòng)畫對(duì)象都是記錄時(shí)間線數(shù)據(jù)的對(duì)象,以最常用的故事板為例,繼承關(guān)系:

? ? Object → DispatcherObject → DependencyObject → Freezable → Animatable?

? ? ? ? → Timeline → TimelineGroup → ParallelTimeline → Storyboard

https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.animation.storyboard


通過(guò) Storyboard 可以控制的動(dòng)畫:的播放 Begin()、暫停 Pause()、恢復(fù) Resume()、查找 Seek()、停止 Stop() 和刪除 Remove()。


關(guān)鍵幀對(duì)象類型定義在 System.Windows.Media.Animation 命名空間,根據(jù)控件屬性數(shù)據(jù)的類型不同,關(guān)鍵幀也有不同的類型,Animatable 抽象類提供動(dòng)畫接口支持。例如,很大一部分是讓一個(gè)屬性在起始值和結(jié)束值之間變化,這種動(dòng)畫對(duì)應(yīng) DoubleAnimation,它可以設(shè)置一個(gè) Duration,在指定的時(shí)間段內(nèi),屬性值從 From 到 To 之間變換。


1. **From**: 起始值,在動(dòng)畫開始的時(shí)候?qū)⒛繕?biāo)屬性設(shè)置為該值;

2. **To**: 結(jié)束值,動(dòng)畫結(jié)束是目標(biāo)屬性為改值;

3. **By**: 偏移值:動(dòng)畫結(jié)束的時(shí)候目標(biāo)屬性為"初始值+偏移值";


根本上說(shuō),雙值動(dòng)畫是一種簡(jiǎn)化的插值方法,Interpolation復(fù)雜一點(diǎn)的是緩動(dòng)函數(shù) Easing Functions,或者稱緩動(dòng)曲線插值算法。通常,動(dòng)畫的兩個(gè)關(guān)鍵幀之間還有補(bǔ)幀,它們需要通過(guò)插值來(lái)獲得一個(gè)確定的狀態(tài)。

https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/graphics-multimedia/easing-functions


WPF 系統(tǒng)內(nèi)置四種插值算法:


1. 線性:補(bǔ)幀均勻變化;

2. 離散:補(bǔ)幀是由離散數(shù)據(jù)確定的,沒(méi)有過(guò)渡效果;

3. 樣條:使用貝塞爾曲線實(shí)現(xiàn)更精確的加速和減速控制;

4. 緩動(dòng):使用緩動(dòng)函數(shù)曲線實(shí)現(xiàn)彈性變化;


作為專攻動(dòng)畫的 WPF 框架,不再有類似 WinForm 中的 Timer 控件,資產(chǎn)工具箱中也沒(méi)有 Timer 控件。System.Windows.Threading 命名空間下的 DispatcherTimer 類是替代方案,這個(gè)定時(shí)器和 UI 運(yùn)行在同一線程上。與系統(tǒng)定時(shí)器不同,System.Timers.Timer 這種定時(shí)器和 UI 并不在同一個(gè)線程,會(huì)觸發(fā)無(wú)效操作。


? ? System.InvalidOperationException:“調(diào)用線程無(wú)法訪問(wèn)此對(duì)象,因?yàn)榱硪粋€(gè)線程擁有該對(duì)象。”


因?yàn)?WPF 中只有 UI 線程才能操作 UI 元素,非 UI 線程要訪問(wèn) UI 時(shí)就會(huì)報(bào)異常。其他線程必須通過(guò) Invoke、委托(安全性)等方式,Winform 可以開啟/關(guān)閉“只允許UI線程修改UI”。

圖形控件的屬性面板及屬性組織:

1. **Brushes** 畫筆:設(shè)置圖形控件的外觀,可以使用純色、漸變色、背景圖或系統(tǒng)預(yù)置色。

2. **Layout** 布局:設(shè)置控件的大小、位置、邊界等基礎(chǔ)排版屬性。

3. **Visibility** 外觀:設(shè)置可見性,透明度,以及濾鏡效果,如模糊效果 BlurEffect。

4. **Automatic** 自動(dòng)化:設(shè)置快捷鍵、提示信息、控件狀態(tài)等等。

5. **Public** 公共屬性:設(shè)置 Cursor、有效性,以及數(shù)據(jù)綁定相關(guān)的 DataContext。

6. **Transform** 仿射變換:這是圖形學(xué)中通用的變換方法,包括平移、旋轉(zhuǎn)、縮放、切變、翻轉(zhuǎn)等等。

7. **Misc** 雜項(xiàng):其它未分類屬性,包括 BindingGroup、ContexMenu,或 Style 等等。


在屬性面板中創(chuàng)建樣式后,可以右鍵菜單“轉(zhuǎn)到源”打開并編輯樣式,也可以直接在對(duì)象與時(shí)間線面板中,使用右鍵菜單 Edit Template - Apply Resource 創(chuàng)建樣式定義。定義好的樣式包含了以上這些屬性設(shè)置,可以復(fù)用在其它控件上。


此外,還有事件處理相關(guān)的屬性,在 Blend 的屬性面板中,有專用于設(shè)置事件處理函數(shù)的列表。

WPF 作為大部分位于 System.Windows 命名空間中的 .NET 類型的一個(gè)子集存在。你可以使用最喜歡的 .NET 編程語(yǔ)言(如 C# 或 Visual Basic)來(lái)完成實(shí)例化類、設(shè)置屬性、調(diào)用方法以及處理事件等操作。


WPF 可視化組件以 Visual 基類派生出關(guān)鍵子類,實(shí)現(xiàn)了 WPF 編程中可用的大量公共元素功能:


01. **UIElement** WPF 核心級(jí)實(shí)現(xiàn)的基類,其它 UI 實(shí)現(xiàn)是在此元素和基本表示特性上生成的。?

02. **ContentElement**? ? 為內(nèi)容元素提供 WPF 核心級(jí)基類。 內(nèi)容元素設(shè)計(jì)用于流樣式顯示,它們使用面向標(biāo)記的直觀布局模型和精心設(shè)計(jì)的簡(jiǎn)單對(duì)象模型。?

03. **FrameworkElement**? 提供 WPF 元素的屬性、事件和方法的 WPF 框架級(jí)別集。 此類表示所提供的 WPF 框架級(jí)別實(shí)現(xiàn)基于 UIElement 定義的 WPF 核心級(jí)別 API。?

04. **FrameworkContentElement**,? 是 ContentElement 基類的 WPF 框架級(jí)別的實(shí)現(xiàn)和擴(kuò)展。增加了針對(duì)下列各項(xiàng)的支持:附加輸入 API(包括工具提示和上下文菜單)、演示圖板、用于數(shù)據(jù)綁定的? ? ?數(shù)據(jù)上下文、格式支持和邏輯樹幫助程序 API。?

05. **Viewport3D** 由 Viewport3DVisual 在指定的二維視區(qū)邊界內(nèi)呈現(xiàn) Visual3D 子對(duì)象。


Visual 對(duì)象是一個(gè)核心 WPF 對(duì)象,它的主要作用是提供呈現(xiàn)支持。 用戶界面控件派生自 Visual 類,并使用該類來(lái)保存它們的呈現(xiàn)數(shù)據(jù)。 Visual 對(duì)象為以下項(xiàng)提供支持:


01. 輸出顯示:呈現(xiàn)視覺(jué)對(duì)象的持久、序列化的繪圖內(nèi)容。

02. 轉(zhuǎn)換:針對(duì)視覺(jué)對(duì)象執(zhí)行轉(zhuǎn)換。

03. 剪裁:為視覺(jué)對(duì)象提供剪裁區(qū)域支持。

04. 命中測(cè)試:確定坐標(biāo)或幾何形狀是否包含在視覺(jué)對(duì)象的邊界內(nèi)。

05. 邊框計(jì)算:確定視覺(jué)對(duì)象的邊框。


Visual 對(duì)象角色的關(guān)鍵之一是,了解**即時(shí)模式**和**保留模式**圖形系統(tǒng)之間的區(qū)別。GDI 或 GDI+ 應(yīng)用程序使用即時(shí)模式圖形系統(tǒng),這意味著 WinForms 應(yīng)用程序由于某項(xiàng)操作(如重設(shè)窗口大小)或者對(duì)象的可視化外觀發(fā)生變化而失效的工作區(qū)部分,將由程序負(fù)責(zé)重新繪制。


相比之下,WPF 使用保留模式系統(tǒng)。 這意味著具有可視化外觀的應(yīng)用程序?qū)ο蠖x一組序列化繪圖數(shù)據(jù)。 在定義了繪圖數(shù)據(jù)之后,系統(tǒng)會(huì)響應(yīng)所有的重新繪制請(qǐng)求來(lái)呈現(xiàn)應(yīng)用程序?qū)ο蟆?甚至在運(yùn)行時(shí),用戶可以修改或創(chuàng)建應(yīng)用程序?qū)ο?,并仍依賴于系統(tǒng)響應(yīng)繪制請(qǐng)求。 保留模式圖形系統(tǒng)中有一個(gè)強(qiáng)大功能,即繪圖信息總是由應(yīng)用程序保持為序列化狀態(tài),但是呈現(xiàn)功能仍由系統(tǒng)負(fù)責(zé)。


使用保留模式圖形的最大好處之一就是,WPF 可以高效優(yōu)化需要在應(yīng)用程序中重繪的內(nèi)容。


? XAML & Code-Behind

WPF 圖形界面應(yīng)用有兩個(gè)最基本的概念 Markup & Code-Behind:

- 代碼:這是一個(gè)應(yīng)用程序最基本的構(gòu)成,代碼經(jīng)過(guò)編譯器的處理,會(huì)轉(zhuǎn)換成 .Net CLR 平臺(tái)上可運(yùn)行的程序;

- XAML:基于 XML 格式化表達(dá)程序圖形界面的類型,及其它層次結(jié)構(gòu),本質(zhì)就是程序代碼要使用到的數(shù)據(jù);


從以上兩個(gè)概念出發(fā),WPF 圖形框架可以看作是一個(gè)負(fù)責(zé)協(xié)調(diào) XMAL 數(shù)據(jù)與 GUI 類庫(kù)層次結(jié)構(gòu),以及事件處理程序、動(dòng)畫效果的開發(fā)工具。WPF 還包括增強(qiáng)屬性和事件的其他編程構(gòu)造: 依賴項(xiàng)屬性 和 路由事件。


XAML 是一種基于 XML 的標(biāo)記語(yǔ)言,像 HTML 一樣以聲明形式實(shí)現(xiàn)應(yīng)用程序的外觀。 通常用它創(chuàng)建窗口、對(duì)話框、頁(yè)和用戶控件,并填充控件、形狀和圖形。


模板創(chuàng)建的 App.xaml 和配套的 App.xaml.cs 是程序的入口,對(duì)應(yīng)?System.Windows.Application 實(shí)例,其屬性 `StartupUri` 指示了程序運(yùn)行的第一個(gè)窗體對(duì)象,同時(shí)可以設(shè)置 `Startup` 指定一個(gè)啟動(dòng)時(shí)要執(zhí)行的事件,可以不設(shè)置 `StartupUri` 而通過(guò)指定的啟動(dòng)事件來(lái)實(shí)例化窗體。

啟動(dòng)事件的代碼就寫在 App.xaml.cs 文件內(nèi),比如 `Startup="App_OnStartup"`:

默認(rèn)的主窗體也一樣有兩個(gè)文件對(duì)應(yīng) System.Windows.Window 對(duì)象。


整個(gè) WPF 程序有兩種開發(fā)模式,XAML 的標(biāo)簽化 UI 編輯模式,可以在 Visual Studio 中拖放對(duì)象組件。

另一種是代碼編寫模式,用來(lái)實(shí)現(xiàn)程序邏輯。WPF 通過(guò) XAML 實(shí)現(xiàn)了 UI 和代碼的分享。這種軟件開發(fā)模式

明顯優(yōu)于 WinForms 舊式的純代碼開發(fā)。


比如,在 MainWindow.xaml 添加一個(gè)按鈕控件對(duì)象:

在 MainWindow.xaml.cs 添加一個(gè)事件處理函數(shù):

當(dāng)構(gòu)造函數(shù)調(diào)用 InitializeComponent 方法時(shí),就會(huì)將標(biāo)記定義的 UI 控件與背后的代碼合并在一起,它生成應(yīng)用程序?yàn)槟_初始化 UI 組件的實(shí)現(xiàn)代碼,包括將按鈕的 Click 事件與事件處理程序關(guān)聯(lián)。這就是 Markup & Code-Behind,用標(biāo)記定義控件,用背后的代碼自動(dòng)實(shí)現(xiàn)。


使用代碼編程,第一個(gè)問(wèn)題是要解決如何獲取 XAML 文檔中定義的對(duì)象。


FrameworkElement 是控件所繼承的基類,并且具有 Resources 屬性。 因此可以將本地資源字典添加到任何 FrameworkElement,它提供 `FindResource()` 查找和引用資源,還提供 `FindName()`方法,根據(jù)名稱來(lái)查找 XAML 文檔節(jié)點(diǎn)定義的其它對(duì)象。


假設(shè)一個(gè) XAML 在 Window.Resources 本地資源中定義了故事板對(duì)象,那么就可以按以下操作獲取引用。要獲取故事板的狀態(tài),可以注冊(cè)事件處理函數(shù)來(lái)獲取其狀態(tài)數(shù)據(jù)。

更好的方法是使用代碼生成工具為 XAML 節(jié)點(diǎn)定義的內(nèi)部成員,通過(guò)翻查 obj 目錄下的生成代碼,可以發(fā)現(xiàn)XAML 中定義的每個(gè)節(jié)點(diǎn)都有一個(gè)相應(yīng)的聲明為 internal 的成員引用它,成員名稱即是 XAML 節(jié)點(diǎn)定義的名稱。比如,XAML 中有節(jié)點(diǎn)名稱為?my_grid,就可以直接使用 this.my_grid 引用它。


? Data Bindding


MVVM 編程模式的一個(gè)實(shí)現(xiàn)方式就是 INotifyPropertyChanged 接口,屬性變換通知機(jī)制可以在屬性數(shù)據(jù)被修改時(shí)觸發(fā)一個(gè)事件通知,綁定到 PropertyChanged 的事件處理函數(shù)就有機(jī)會(huì)響應(yīng),數(shù)據(jù)變更這一行為就變成了觸發(fā)一個(gè)事件,通常這個(gè)事件會(huì)用來(lái)更新用戶界面,即 MVVM 編程模式中稱作視圖 View 的部分。View 通常通過(guò) XAML 文件中定義的 `BindingContext` 綁定 ViewModel 的實(shí)例為其提供數(shù)據(jù)。


隨著編程技術(shù)的發(fā)展,“屬性”這一概念也由 Attribute 轉(zhuǎn)變?yōu)?Property,從簡(jiǎn)單的數(shù)據(jù)轉(zhuǎn)換成為“財(cái)產(chǎn)”。并且,邏輯上加入了控制權(quán):

在 WPF 框架的類結(jié)構(gòu)中,幾乎所有的控件都間接繼承自 DependencyObject 類型,并通過(guò) DependencyProperty 給屬性引入依賴管理機(jī)制,定義一個(gè)依賴屬性,就要向此機(jī)構(gòu)注冊(cè)它。當(dāng)依賴屬性被修改后,即觸發(fā) OnPropertyChanged 事件通知,示范如下:

數(shù)據(jù)保存在 DependencyProperty 內(nèi)部的一個(gè) IDictionary 字典中,一條記錄中的鍵(Key)就是

該屬性的 HashCode,而值(Value)則是已注冊(cè)好的 DependencyProperty。


為了方便獲取方法的名稱并傳遞給依賴者,可以使用 System.Runtime.CompilerServices 命名空間下

提供的一系列編譯獲取信息的標(biāo)注,其中就有:


- **CallerMemberNameAttribute** 獲取方法調(diào)用方的方法或?qū)傩悦Q。


綁定允許用戶更改數(shù)據(jù),然后將該數(shù)據(jù)傳播回源對(duì)象?;蛘?,可能不希望允許用戶更新源數(shù)據(jù)??梢栽O(shè)置

Binding.Mode 來(lái)控制數(shù)據(jù)流。


完成一個(gè)綁定,需要有 Source、Binding Object 和 Target 三方,不同類型的數(shù)據(jù)流控制方式:


- **OneWay** 大多數(shù)屬性默認(rèn)綁定,源屬性的更改會(huì)自動(dòng)更新目標(biāo)屬性,但目標(biāo)屬性的更改不會(huì)傳播回源屬性。

- **TwoWay** 交互式控件默認(rèn)綁定,更改源屬性或目標(biāo)屬性時(shí)會(huì)自動(dòng)更新另一方,如 TextBox.Text 和 CheckBox.IsChecked。

- **OneWayToSource** 綁定與 OneWay 綁定相反;當(dāng)目標(biāo)屬性更改時(shí),它會(huì)更新源屬性。


用于確定依賴屬性綁定在默認(rèn)情況下是單向還是雙向的編程方法是:


- 使用 DependencyProperty.GetMetadata 獲取屬性元數(shù)據(jù),

- 然后檢查 FrameworkPropertyMetadata.BindsTwoWayByDefault 屬性的布爾值。


靜態(tài)綁定在第一次生成界面時(shí),并且永遠(yuǎn)不會(huì)發(fā)生更改。


以下是一個(gè) StaticResource 數(shù)據(jù)綁定示范:

  1. ?在 Resources 屬性中定義數(shù)據(jù)源;

  2. ?設(shè)置 DockPanel 的 DataContext 屬性,創(chuàng)建數(shù)據(jù)綁定;

  3. ?然后將數(shù)據(jù)源綁定到 Button 節(jié)點(diǎn)的 Background 屬性上。


? Triggers & Routed Events

觸發(fā)器,Trigger,即按條件應(yīng)用屬性值或執(zhí)行操作的一類對(duì)象,可以直接在 XAML 中可以供設(shè)計(jì)人員使用,這是一個(gè)不需要需編寫代碼也能做不少事的工具。注意 Blend for Visual Studio 社區(qū)版需要使用代碼方式添加觸發(fā)器。


FrameworkElement.Triggers 獲取直接在此元素上或在子元素中建立的觸發(fā)器的集合。


Trigger 對(duì)象具有 Setters, EnterActions, ExitActions 等屬性,這些屬性根據(jù)特定屬性的狀態(tài)應(yīng)用更改或操作。EventTrigger 對(duì)象在發(fā)生指定的路由事件時(shí)啟動(dòng)一組 Actions。


以下是一些常用到觸發(fā)器的對(duì)象類型:

01. 所有控件觸發(fā)(FrameworkElement.Triggers)

02. 樣式觸發(fā)(Styles.Triggers)

03. 控件模板觸發(fā)(ControlTemplate.Triggers)

04. 數(shù)據(jù)模板觸發(fā)(DataTemplate.Triggers)


例如,當(dāng)鼠標(biāo)指針位于某個(gè)用戶界面 (UI) 控件上時(shí),可能需要使用 EventTrigger 來(lái)啟動(dòng)一組動(dòng)畫。 EventTrigger 沒(méi)有狀態(tài)終止的概念,因此一旦引發(fā)事件的條件不再成立,操作將不會(huì)撤消。

通常,可選擇在每個(gè)按鈕的 Triggers 集合中放置事件觸發(fā)器。然而,對(duì)于動(dòng)畫這種方法不能工作。解決方法是在一個(gè)地方定義所有事件觸發(fā)器,例如,在頂級(jí)元素的 Triggers 集合中。這樣,就可以在用戶界面中將按鈕移到不同的位置,而不會(huì)禁用他們的功能。


使用 EventTrigger.SourceName 屬性關(guān)聯(lián)事件觸發(fā)器,只要此屬性和按鈕的 Name 屬性相匹配,觸發(fā)器就會(huì)應(yīng)用到恰當(dāng)?shù)陌粹o上。


注意,BeginStoryboard 要播放其它故事板,必須為動(dòng)作指定目標(biāo)的名稱,Name 屬性要與。其他觸發(fā)器通過(guò) BeginStoryboardName 屬性指定相同名稱,連接到相同的故事板。


如果要觸發(fā)其它已經(jīng)定義好的故事板動(dòng)畫,可以通過(guò) BeginStoryboard 的 Storyboard 屬性綁定。



路由事件”,可以從功能或?qū)崿F(xiàn)的角度來(lái)理解它。


- 功能定義:路由事件是一種可以針對(duì)元素樹中的多個(gè)偵聽器調(diào)用處理程序的事件。

- 實(shí)現(xiàn)定義:路由事件是一個(gè) CLR 事件,由 RoutedEvent 類的實(shí)例提供支持并由 WPF 事件系統(tǒng)處理。


請(qǐng)思考下面的簡(jiǎn)單元素樹:

在這個(gè)簡(jiǎn)化的元素樹中,Click 事件的源是某個(gè) Button 元素,而所單擊的 Button 是有機(jī)會(huì)處理該事件的第一個(gè)元素。 但是,如果附加到 Button 的所有處理程序均未處理該事件,則該事件向上浮升到元素樹中的父級(jí)(即 StackPanel),還可能會(huì)浮升到 Border,然后會(huì)到達(dá)元素樹的根節(jié)點(diǎn)。


換言之,此 Click 事件的事件路由為:

? ? Button-->StackPanel-->Border-->...

路由事件是一個(gè) CLR 事件,它由 RoutedEvent 類的實(shí)例提供支持并向 WPF 事件系統(tǒng)注冊(cè)。 從注冊(cè)中獲取的 RoutedEvent 實(shí)例,通常保留為特定類的 public static readonly 字段成員,該類注冊(cè)路由事件并因此“擁有”路由事件。 與同名 CLR 事件(有時(shí)稱為“包裝器”事件)的連接是通過(guò)替代 CLR 事件的 add 和 remove 實(shí)現(xiàn)來(lái)完成的。路由事件的支持和連接機(jī)制在概念上與以下機(jī)制相似:依賴屬性是一個(gè) CLR 屬性,該屬性由 DependencyProperty 類提供支持并向 WPF 屬性系統(tǒng)注冊(cè)。


以下示例演示自定義 Tap 路由事件的聲明,其中包括注冊(cè)和公開 RoutedEvent 標(biāo)識(shí)符字段以及對(duì) Tap CLR 事件進(jìn)行 add 和 remove 實(shí)現(xiàn)。

XAML 定義了一種語(yǔ)言組件和稱為 attached-events 的事件類型。 通過(guò)附加事件的概念,你能夠向任意元素(而不是實(shí)際定義或繼承事件的元素)添加特定事件的處理程序。 在這種情況下,對(duì)象既不會(huì)引發(fā)事件,目標(biāo)處理實(shí)例也不會(huì)定義或“擁有”事件。


? 參考

- https://github.com/dotnet/wpf

- https://learn.microsoft.com/zh-cn/visualstudio/xaml-tools/creating-a-ui-by-using-xaml-designer-in-visual-studio

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/graphics-multimedia/animation-overview

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/wpf-architecture

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/xaml-in-wpf

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/getting-started/whats-new

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/getting-started/walkthrough-my-first-wpf-desktop-application

- https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/data/data-binding-overview

- https://www.cnblogs.com/KnightsWarrior/archive/2010/08/27/1809739.html

- https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.dependencyobject

- https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.dependencyproperty

- https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.propertymetadata


WPF 昨日黃花?趁它黃之前入一下門吧!的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
博白县| 渑池县| 卓尼县| 阳江市| 敖汉旗| 喜德县| 盈江县| 报价| 肥乡县| 余姚市| 廉江市| 靖边县| 静海县| 绥化市| 仙游县| 信阳市| 黄石市| 社旗县| 正阳县| 南宁市| 玉林市| 衡东县| 赤壁市| 修水县| 红安县| 上栗县| 海林市| 互助| 塔城市| 横山县| 台中县| 永平县| 错那县| 河池市| 吉安县| 阿城市| 天峻县| 田东县| 遂川县| 沙田区| 岑溪市|