WPF為我們準(zhǔn)備了完善的命令系統(tǒng),你可能會(huì)問(wèn):“有了路由事件為何還需要命令系統(tǒng)呢?”。事件的作用是發(fā)布、傳播1些消息,消息轉(zhuǎn)達(dá)到了接收者,事件的指令也就算完成了,至于如何響應(yīng)事件送來(lái)的消息事件其實(shí)不做任何限制,每一個(gè)接收者可已用自己的行動(dòng)來(lái)響應(yīng)事件。也就是說(shuō),事件不具有束縛力。命令和事件的區(qū)分就在于命令具有束縛力。
下面直接給出其組成元素:
?命令(Command)實(shí)現(xiàn)了ICommand接口的類(lèi),使用比較多的是RoutedCommand。
?命令源(Command Source)命令的發(fā)送者,現(xiàn)實(shí)了ICommandSource接口的類(lèi),實(shí)現(xiàn)此類(lèi)的元素主要有ButtonBase,Hyperlink,MenuItem、ListBoxItem等
?命令目標(biāo)(Command Target)命令的接受者,實(shí)現(xiàn)了IInputElement接口的類(lèi)。
?命令關(guān)聯(lián)(Command Binding)負(fù)責(zé)把外圍的邏輯與命令關(guān)聯(lián)起來(lái)。
相對(duì)事件的元夙來(lái)說(shuō),命令元素之間的關(guān)系還是會(huì)復(fù)雜1些,具體的關(guān)系會(huì)通過(guò)命令的使用來(lái)講明。下面先簡(jiǎn)單介紹1下自定義命令的步驟。
a、創(chuàng)建命令類(lèi)
如果命令沒(méi)有觸及到業(yè)務(wù)邏輯的話,1般使用WPF類(lèi)庫(kù)的RoutedCommand類(lèi)便可,如果要聲明相對(duì)邏輯復(fù)雜1些的類(lèi),可以實(shí)現(xiàn)RouteCommand類(lèi)的繼承或是ICommand的接口。
b、聲明命令實(shí)例
由于命令的普遍性,1般情況下程序中某類(lèi)命令只需要1個(gè)命令實(shí)例便可(單件模式)。
c、指明命令的源
通常是可以點(diǎn)擊的控件,命令還有個(gè)好處就是,沒(méi)有準(zhǔn)備好的命令,這個(gè)控件不可用。如果把命令看作炮彈,那末命令源相當(dāng)于火炮,這個(gè)火炮還是防走火的。
d、指明命令的目標(biāo)
目標(biāo)是命令的作用對(duì)象。如果指定了目標(biāo),不管是不是有焦點(diǎn),都會(huì)遭到這個(gè)命令。如果沒(méi)有指定目標(biāo)的話,具有焦點(diǎn)的對(duì)象默許為命令目標(biāo)。還有1個(gè)要注意的是設(shè)置目標(biāo)是通過(guò)命名的源來(lái)設(shè)置的。格式為:命令源控件.CommandTarget = 目標(biāo)控件;
e、設(shè)置命令關(guān)聯(lián)
關(guān)于設(shè)置命令關(guān)聯(lián)還是在實(shí)例中好好的體會(huì)1下吧。下面就通過(guò)1個(gè)例子來(lái)講明。
下面的例籽實(shí)現(xiàn)的是點(diǎn)擊按鈕時(shí),清除文本框里面的內(nèi)容。由于代碼注釋寫(xiě)的比較詳細(xì),直接給代碼,然后具體再解釋:
XAML:
第1,使用命令可以免自己寫(xiě)代碼判斷Button是不是可以用和添加快捷鍵。
第2,RountedCommand是1個(gè)與業(yè)務(wù)邏輯無(wú)關(guān)的類(lèi),只負(fù)責(zé)在程序中跑腿而其實(shí)不對(duì)命令目標(biāo)進(jìn)行操作,TextBox其實(shí)不是由它清空的。那末TextBox的情況操作是誰(shuí)呢?答案是CommandBinding。由于不管是探測(cè)命令是不是可以履行還是命令投遞目標(biāo),都會(huì)激起命令目標(biāo)發(fā)送路由事件,這些事件會(huì)沿著UI元素樹(shù)向上傳遞,終究被CommandBinding所捕捉。本例中CommandBinding被安裝在外圍的StackPanel上,Commandbinding站在高處起1個(gè)偵聽(tīng)器的作用,而且專門(mén)針對(duì)rouutedCommand命令捕捉與其相干的事件。本例中,當(dāng)CommandBinding捕捉到CanExecute就會(huì)調(diào)用cb_CanExecute方法。當(dāng)捕捉到是Executed的時(shí)候,就調(diào)用cb_Execute事件。
第3,由于CanExecute事件的激起頻率比較高,為了不下降性能,在處理終了以后建議將e.Handle設(shè)置為true。
第4,CommandBinding1定要設(shè)置在命令目標(biāo)的外圍控件上,不然沒(méi)法捕捉CanExecute和Executed等路由事件。
命令具有1處聲明,處處使用的特點(diǎn),比如Save命令,在程序的任何地方它都表示要求命令目標(biāo)保存數(shù)據(jù)。因此,微軟在WPF類(lèi)庫(kù)里面準(zhǔn)備了1些便捷的命令庫(kù),這些命令庫(kù)包括:
ApplicationCommands
ComponentCommands
NavigationCommands
MediaCommands
EditingCommands
它們都是靜態(tài)類(lèi),而命令就是由這些靜態(tài)類(lèi)的只讀屬性以單件模式暴露出來(lái)的。例如:ApplicationCommands類(lèi)就包括CancelPrint、Close、ContextMenu、Copy、CorrectionList、Cut、Delete、Find、Help、New、NotACommand、Open、Paste、Print、PrintPreview、Properties、Redo、Replace、Save、SaveAs、SelectAll、Stop、Undo這些命令。
這就引發(fā)了1個(gè)問(wèn)題:如果界面上有兩個(gè)按鈕1個(gè)用來(lái)創(chuàng)建Student檔案,1個(gè)用來(lái)創(chuàng)建Teacher檔案。都使用New命令的話,程序應(yīng)當(dāng)如何區(qū)分新建的是甚么檔案呢?
答案是使用CommandParameter,命令源1定是實(shí)現(xiàn)了ICommandSource接口的對(duì)象,而ICommandSource有1個(gè)屬性就是CommandParameter,如果把命令看做飛向目標(biāo)的炮彈,那末CommandParameter就相當(dāng)于裝載在炮彈里面的“消息”。下面是程序的實(shí)現(xiàn)代碼。
XAML: