CommandBinding機(jī)制剖析及應(yīng)用*****************************最近正在學(xué)習(xí)WPF,因此,有時(shí)間時(shí)會(huì)寫一些小文章,介紹Wpf中一些比較有趣和重要的東西。學(xué)習(xí)并應(yīng)用技術(shù)的過(guò)程就是一個(gè)“技術(shù)拼圖”的過(guò)程,只有將各個(gè)技術(shù)碎片拼成一張完整的大圖,才算是“功德圓滿”。本文就是這張WPF技術(shù)全景拼圖中的一小塊。金旭亮2008-10-21****************" />

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Command Binding機(jī)制剖析及應(yīng)用

系統(tǒng) 2132 0

WPF 技術(shù)拼圖之

<?xml:namespace prefix = o />

Command Binding 機(jī)制剖析及應(yīng)用

*****************************

最近正在學(xué)習(xí)WPF,因此,有時(shí)間時(shí)會(huì)寫一些小文章,介紹Wpf中一些比較有趣和重要的東西。

學(xué)習(xí)并應(yīng)用技術(shù)的過(guò)程就是一個(gè)“技術(shù)拼圖”的過(guò)程,只有將各個(gè)技術(shù)碎片拼成一張完整的大圖,才算是“功德圓滿”。

本文就是這張WPF技術(shù)全景拼圖中的一小塊。


金旭亮

2008-10-21


*****************************



WPF 中,有一個(gè)非常有意思的 Command Binding (命令綁定機(jī)制),這種機(jī)制在原有的 Windows Form 中沒有提供。本文設(shè)計(jì)了一個(gè)實(shí)例,直觀地展示出 Command Binding 的應(yīng)用場(chǎng)景,并對(duì)其機(jī)制進(jìn)行了剖析。

1 Command Binding 有什么用?

這個(gè)機(jī)制有何作用?看一下下面這個(gè)例子就清楚了( 1 ),此例是由 Visual C# 2008 Express 創(chuàng)建的標(biāo)準(zhǔn) Wpf 應(yīng)用程序,項(xiàng)目中有一個(gè) Window1.xaml 作為主窗體:


Command Binding機(jī)制剖析及應(yīng)用

1

從圖中可以看到,窗體上有一個(gè)菜單和一個(gè)按鈕,當(dāng)用戶點(diǎn)擊這兩個(gè)控件時(shí),它們執(zhí)行相同的功能。

多個(gè)控件執(zhí)行同一個(gè)功能在桌面應(yīng)用程序中是非常常見的,比如相同的命令可以通過(guò)選擇“菜單”命令或點(diǎn)擊工具欄上的特定按鈕執(zhí)行。

以傳統(tǒng)方式開發(fā)這樣的程序,往往需要針對(duì)每個(gè)控件的 Click 事件分別編碼來(lái)實(shí)現(xiàn)。

然而,在許多時(shí)候我們需要同步多個(gè)控件的狀態(tài)。比如在一個(gè)文本編輯器中 ,當(dāng)用戶沒有選中任何文本時(shí),菜單中的“ Copy ”和工具欄上的“ Copy ”按鈕都需要禁用,因此,傳統(tǒng)方式下還必須寫額外代碼來(lái)實(shí)現(xiàn)這一點(diǎn)。

Command Binding 彌補(bǔ)傳統(tǒng)編程方式的缺陷,可以幫助我們以很少的代碼實(shí)現(xiàn)同樣的功能。

2 實(shí)現(xiàn) Command Binding

讓我們修改示例以利用命令綁定機(jī)制。

首先,向項(xiàng)目中加入一個(gè) MyAppCommands 類,其內(nèi)容如下:

namespace UnderStandCommandBinding

{

public class MyAppCommands

{

public static RoutedUICommand MyCommand = new RoutedUICommand ();

}

}

請(qǐng)?zhí)貏e注意其中的 RoutedUICommand 類型的字段 MyCommand 。它定義了一個(gè)將被窗體控件所調(diào)用的命令。

Window1.cs 中書寫以下代碼:

partial class Window1 : Window

{

public Window1()

{

InitializeComponent();

CommandBinding cb = new CommandBinding();

cb.Command = MyAppCommands .MyCommand;

cb.Executed += new ExecutedRoutedEventHandler(cb_Executed);

}

void cb_Executed(object sender, ExecutedRoutedEventArgs e)

{

MessageBox.Show(" 響應(yīng)自定義命令 MyCommand");

}

}

上述代碼創(chuàng)建一個(gè) CommandBinding 對(duì)象,此對(duì)象指明 cb_Executed 函數(shù)響應(yīng) MyCommand 命令(其實(shí)是被 MyCommand 命令的 Execute 方法自動(dòng)調(diào)用,這里借用事件處理機(jī)制的相關(guān)術(shù)語(yǔ)以便于理解,事實(shí)上,命令綁定與事件響應(yīng)不是一回事,簡(jiǎn)單地說(shuō),命令綁定建構(gòu)于 Wpf 的事件路由機(jī)制之上)。

下一步則需要指定窗體上的哪幾個(gè)控件用于調(diào)用此命令:

partial class Window1 : Window

{

public Window1()

{

InitializeComponent();

// 創(chuàng)建命令對(duì)象

CommandBinding cb = new CommandBinding ();

cb.Command = MyAppCommands .MyCommand;

cb.Executed += new ExecutedRoutedEventHandler (cb_Executed);

// 將要執(zhí)行的命令對(duì)象添加到窗體的命令對(duì)象集合中

this.CommandBindings.Add(cb);

// 設(shè)定菜單項(xiàng)和按鈕都執(zhí)行 MyCommand 命令

mnuInvokeMyCommand.Command = MyAppCommands.MyCommand;

btnInvokeMyCommand.Command = MyAppCommands.MyCommand;

}

void cb_Executed(object sender, ExecutedRoutedEventArgs e)

{

MessageBox .Show( " 響應(yīng)自定義命令 MyCommand" );

}

}

現(xiàn)在運(yùn)行程序,可以發(fā)現(xiàn),單擊菜單項(xiàng)和按鈕都會(huì)調(diào)用 cb_Executed 函數(shù)。

3 使用 XAML 實(shí)現(xiàn) DataBinding

前面使用代碼實(shí)現(xiàn)了數(shù)據(jù)綁定。現(xiàn)在,改用 XAML 實(shí)現(xiàn)相同的功能。

首先,刪除 Window1 構(gòu)造函數(shù)中的代碼,只留下 cb_Executed ()函數(shù):

partial class Window1 : Window

{

public Window1()

{

InitializeComponent();

}

void cb_Executed(object sender, ExecutedRoutedEventArgs e)

{

MessageBox .Show( " 響應(yīng)自定義命令 MyCommand" );

}

}

回到 Window1.xaml 文件中,首先,在其 Window 元素中加入對(duì)本項(xiàng)目命名空間的引用(其目的是在 XAML 中使用代碼中的類):

<Window x : Class ="UnderStandCommandBinding.Window1" ……

xmlns:myapp="clr-namespace:UnderStandCommandBinding" >

……

</Window

然后,修改 MenuItem 的聲明,加上 Command 屬性:

< MenuItem Header ="Invoke My Command" Name ="mnuInvokeMyCommand" Command="MyAppCommands.MyCommand" />

再修改 Button 的聲明,也加上 Command 屬性:

< Button Name ="btnInvokeMyCommand"

Command="myapp:MyAppCommands.MyCommand">

Invoke My Command

</ Button >

最后,給最頂層元素 Window 添加命令綁定:

< Window.CommandBindings >

< CommandBinding

Command="myapp:MyAppCommands.MyCommand"

Executed="cb_Executed" />

</ Window.CommandBindings >

現(xiàn)在運(yùn)行示例,可以看到運(yùn)行效果與代碼一樣。

由此可知,我們可使用 XAML 以比使用 C# 編寫代碼方式更少的代碼量實(shí)現(xiàn)同樣的功能。

4 實(shí)現(xiàn)控件同步

現(xiàn)在開始展示一下命令綁定的神奇之處。向窗體上加入一個(gè) CheckBox (取名 chkActivateCommand ),我們將用它來(lái)控制是否可以執(zhí)行 MyCommand 命令( 2 ):


Command Binding機(jī)制剖析及應(yīng)用


2

修改命令綁定對(duì)象:

< Window.CommandBindings >

< CommandBinding Command ="myapp:MyAppCommands.MyCommand" Executed ="cb_Executed" CanExecute="CommandBinding_CanExecute" />

</ Window.CommandBindings >

Window.xaml.cs 中添加一個(gè)新函數(shù):

private void CommandBinding_CanExecute(

object sender, CanExecuteRoutedEventArgs e)

{

e.CanExecute = chkActivateCommand.IsChecked.Value;

}

其余代碼不需要?jiǎng)印? OK 。現(xiàn)在運(yùn)行一下示例程序:


Command Binding機(jī)制剖析及應(yīng)用


3

可以看到,現(xiàn)在按鈕和菜單命令的激活與由 CheckBox 控制了。我們甚至沒有寫一行代碼去同步這三個(gè)控件的狀態(tài)!

5 向命令傳送參數(shù)

添加一個(gè)文本框 txtPara 用于輸入?yún)?shù)。

< TextBox Name ="txtPara" Background ="Wheat" />

控件的 CommandParameter 屬性可用來(lái)向命令對(duì)象提供參數(shù),我們使用數(shù)據(jù)綁定機(jī)制將文本框中的文本作為命令參數(shù):

< MenuItem Header ="Invoke My Command" Name ="mnuInvokeMyCommand" Command ="myapp:MyAppCommands.MyCommand" CommandParameter="{Binding ElementName=txtPara,Path=Text}" />

……

< Button Height ="23" Name ="btnInvokeMyCommand" HorizontalAlignment ="Center" Command ="myapp:MyAppCommands.MyCommand" CommandParameter="{Binding ElementName=txtPara,Path=Text}" > Invoke My Command </ Button >

傳入的參數(shù)會(huì)被命令響應(yīng)函數(shù)的 ExecutedRoutedEventArgs 參數(shù)接收,示例程序中修改后的命令響應(yīng)函數(shù)如下:

void cb_Executed( object sender, ExecutedRoutedEventArgs e)

{

MessageBox .Show( e.Parameter.ToString() );

}

運(yùn)行屏幕截圖如 4


Command Binding機(jī)制剖析及應(yīng)用


4

在文本框中輸入文字,點(diǎn)擊按鈕或菜單項(xiàng),將彈出一個(gè)消息框顯示用戶輸入的文本。

我們的示例到此結(jié)束。

6 Command Binding 有何用處?

根據(jù)這個(gè)例子,大家體會(huì)到了 Command Binding 的好處了嗎?

仔細(xì)看一下 MyAppCommands 類,就發(fā)現(xiàn)我們可以向其中添加多個(gè)自定義的命令,只需指定好這些命令對(duì)象的 Execute CanExecute 兩個(gè)事件響應(yīng)屬性,就可以方便地設(shè)定窗體上的控件執(zhí)行特定的命令(通過(guò)其 Command 屬性),而且 WPF 框架會(huì)自動(dòng)幫助我們同步這些控件的狀態(tài)!

這樣一來(lái),我們就得到了一種比較模塊化的 Wpf 桌面應(yīng)用程序結(jié)構(gòu):

(1) 將應(yīng)用程序要執(zhí)行的功能封裝到中間層組件或獨(dú)立的類中;

(2) 創(chuàng)建一個(gè)專用保存命令對(duì)象的類(比如本例中的 MyAppCommands 類),在此類中集中存放應(yīng)用程序要執(zhí)行的命令對(duì)象。

(3) 在窗體中創(chuàng)建命令綁定對(duì)象,為每個(gè)命令對(duì)象創(chuàng)建響應(yīng)函數(shù),并將其添加到 Window 對(duì)象的 CommandBindings 屬性中,之后,即可將控件與命令對(duì)象相互綁定。

這種架構(gòu)的優(yōu)點(diǎn)是增強(qiáng)了代碼的隔離性,并減少了總體的代碼量:

(1) 業(yè)務(wù)邏輯代碼在中間層中;

(2) 專用于提供特定命令對(duì)象的類實(shí)際上成了一個(gè)功能調(diào)用接口層,可以很方便地增刪調(diào)整程序提供的功能。

(3) 現(xiàn)在控件基本上不需要寫大量的代碼響應(yīng)特定的事件和同步多個(gè)控件的狀態(tài)。

7 剖析 Command Binding 機(jī)制

Command Binding 機(jī)制主要與兩個(gè)接口密切相關(guān):一個(gè)是 ICommand ,用于定義命令對(duì)象類,另一個(gè)是 ICommandSource ,用于定義可發(fā)出“調(diào)用命令”的源控件。 RoutedUICommand 類實(shí)現(xiàn)了 ICommand 接口,通常用此類的對(duì)象表示應(yīng)用程序需要執(zhí)行的命令。而 Button 等控件則實(shí)現(xiàn)了 ICommandSource 接口,并且擁有此接口所定義的 Command CommandParameter 屬性,可用于調(diào)用命令。

Wpf 程序主要通過(guò)以下兩種對(duì)象實(shí)現(xiàn)命令綁定: CommandBinding 對(duì)象將命令對(duì)象綁定到特定的命令處理函數(shù)(示例就是這樣的),當(dāng)執(zhí)行命令對(duì)象時(shí),這些命令處理函數(shù)被調(diào)用(命令對(duì)象和命令響應(yīng)函數(shù)的這種關(guān)系稱為“綁定”)。 InputBinding 對(duì)象將命令對(duì)象與特定的按鍵關(guān)聯(lián)起來(lái),當(dāng)用戶按下特定鍵時(shí),相關(guān)聯(lián)的命令對(duì)象被調(diào)用。

許多 Wpf 控件都擁有 CommandBindings InputBindings 兩個(gè)集合屬性,其中成員就是 CommandBinding 對(duì)象和 InputBinding 對(duì)象,從而使這些控件能夠響應(yīng)特定的命令,比如 TextBox 就是這樣,它在內(nèi)部包容了響應(yīng)標(biāo)準(zhǔn)的 Cut/Copy/Paste 命令對(duì)象的代碼,而 wpf 默認(rèn)提供的 ApplicationCommands 類則定義了 Cut/Copy/Paste 命令對(duì)象,這就是為何我們可以不寫一行代碼直接在 TextBox 中使用 Ctl-C 等命令的緣故。

Command Binding 機(jī)制的內(nèi)部機(jī)制比較復(fù)雜,簡(jiǎn)單地說(shuō):

執(zhí)行 Command 對(duì)象時(shí),會(huì)引發(fā) PreviewExecute/Execute PreviewCanExecute/CanExecute 事件,這些事件都是 RoutedEvent ,可以在 Wpf 元素樹中傳播(從樹葉到樹根方向稱為 Bubble ,從樹根到樹葉方向稱為 tunnel ),正是這種事件路由機(jī)制構(gòu)筑了整個(gè) Command Binding 機(jī)制運(yùn)轉(zhuǎn)起來(lái)的根基。

再進(jìn)一步追問一下,事件路由是如何實(shí)現(xiàn)的?這就涉及到 Wpf 另一個(gè)非常重要的新特性——依賴屬性。

有關(guān)路由事件和依賴屬性的剖析,將會(huì)在另外的文章中進(jìn)行介紹。需要指出的是,如果您對(duì) .NET 2.0 所提供的委托、事件等還不清楚,那么,要弄明白 wpf 的路由事件和依賴屬性比較困難。

這也再次驗(yàn)證了一句老話:新路接在舊路的前頭。

好,這篇文章就寫到這里吧!

Command Binding機(jī)制剖析及應(yīng)用


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 西峡县| 靖宇县| 浮梁县| 华坪县| 吕梁市| 敦化市| 容城县| 盘锦市| 肥城市| 泰和县| 伊川县| 马鞍山市| 德安县| 苍南县| 克什克腾旗| 大厂| 文昌市| 芦溪县| 汉源县| 苍南县| 佛山市| 永清县| 封丘县| 昭平县| 新乡县| 盐亭县| 庄浪县| 通州市| 县级市| 玛纳斯县| 浦江县| 遂昌县| 望奎县| 资溪县| 通江县| 平舆县| 类乌齐县| 嘉定区| 崇阳县| 禹州市| 武乡县|