2012-08-05 26 views
6

我目前正在學習WPF和MVVM,我想我得到它的大部分和它是如何工作的,但我遇到了使用RelayCommand(或DelegateCommand)的東西,我不明白。我認爲這與代表們的工作方式有關。繼電器命令和無參數執行方法

請注意下面的代碼目前都在測試解決方案中,所以沒有實時代碼。另外我正在考慮這個不需要像close這樣的參數的命令,並且理解它爲什麼起作用。

所以,如果我走RelayCommand該約什史密斯創建(http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030)我可以設置這樣一個命令:

RelayCommand updateTextContentCommand; 

public ICommand UpdateTextContentCommand 
{ 
    get 
    { 
     if (updateTextContentCommand == null) 
     { 
      updateTextContentCommand = new RelayCommand(
       param => this.UpdateTextContentCommand_Execute()); 
     } 
     return updateTextContentCommand; 
    } 
} 

與此執行方法:

public void UpdateTextContentCommand_Execute() 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

我用一個簡單的結合一個TextBlock來查看結果並將該命令綁定到一個按鈕。這工作正常。我沒有得到的是使用lambda表達式來創建命令。 Action<object>需要一個參數不是嗎?那麼爲什麼這個代碼工作?

如果我改變上面的代碼

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

我得到這些錯誤:

*爲最佳重載方法匹配 'MVVM.RelayCommandTesting.Framework.RelayCommand.RelayCommand(System.Action)'有一些無效參數

參數1:無法從「空」到「System.Action」 *

和取出()轉換後執行給出了這樣的錯誤:

參數1:無法從「方法組」轉換爲「System.Action」

但是,如果我改變這樣的代碼:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

public void UpdateTextContentCommand_Execute(object param) 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

它符合並運行良好。如果我改變視圖來使用CommandParameter,那麼我可以使用param來設置使用這種方法的文本內容,但是如果我使用lambda樣式,我必須將一個參數傳遞給該行,所以它的參數=>this.UpdateTextContentCommand_Execute(param)

在我的測試中,我對CommandParameter值進行了硬編碼,但我想它很可能是數據綁定到實際系統中的ViewModel的屬性,因此您可以在lambda樣式中傳遞該參數。

任何人都可以解釋爲什麼無參數版本使用lambda樣式嗎?

感謝您花時間閱讀本文。

看來下面的問題也有關於lambda的一些問題,但我沒有看到它回答了我的問題。

Passing a parameter using RelayCommand defined in the ViewModel (from Josh Smith example)

+0

+1爲證明你已經嘗試過的東西了詳細的問題。 – 2012-08-05 12:54:24

+0

乾杯。當我發現問題時,我總是努力並付出努力,因爲我在尋找答案時發現了有用的問題。 – Kioshiki 2012-08-05 12:59:24

回答

8

構造符參數是具有以下簽名的委託:

void MethodName(T parameter) 

其中參數是T型的(在RelayCommand的情況下,這將是system.Object類型的

此編號:

param => this.UpdateTextContentCommand_Execute() 

lambda表達,基本上擴展到這一點:

void AnonymousMethod(object param) 
{ 
    this.UpdateTextContentCommand_Execute(); 
} 

因此,在這種情況下,你傳遞你只是不使用它的參數(param)。 如果你明白這一點,那麼你現在應該知道爲什麼你的其他例子表現他們的方式。

實施例1

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

這裏你正在調用返回空隙的方法。構造函數期待的是,Action<T>委託因此錯誤匹配的東西。

實施例2

如果隨後刪除這樣的括號:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

將這看作是有點像訂閱的事件:

myObject.myevent += new Action<object>(this.UpdateTextContentCommand_Execute); 

其可以縮短爲:

myObject.myevent += this.UpdateTextContentCommand_Execute; 

所以構造函數接受具有簽名,IE瀏覽器

void UpdateTextContentCommand_Execute(object parameter) 

你的方法Action<T>委託簽名相匹配的任何方法具有以下特徵:

void UpdateTextContentCommand_Execute() 

正如你所看到的簽名唐不匹配,所以編譯器抱怨。

當您更新UpdateTextContentCommand_Execute方法接受一個對象參數是簽名匹配現在這就是爲什麼它現在的作品。

+0

謝謝,你所花費的實例方法(AnonymousMethod)使這一切水到渠成我。我認爲這是一個'看不到樹木'的情況。我沒有使用過多的lambda表達式,但是我已經使用了Linq。我只是想看到連接。 – Kioshiki 2012-08-05 12:51:42

+0

我有完全相同的問題。當我有那個'啊哈'的時刻,一切都落空了,突然之間lambda表達式變得更容易理解。我很高興能夠以幫助別人的方式表達我的經歷。 – 2012-08-05 12:53:42