簡體   English   中英

DelegateCommand 的 CanExecute 邏輯

[英]CanExecute Logic for DelegateCommand

更新:焦點變成了 MVVM 而不是實際問題,所以我正在更新它。

我在使用CanExecute for DelegateCommand遇到問題。 在我調用RaiseCanExecuteChanged之前它不會更新,這是所需的行為嗎?

在此處輸入圖片說明

我在這里上傳了一個簡單的示例項目來重現這個問題: http : //dl.dropbox.com/u/39657172/DelegateCommandProblem.zip

問題是,我有兩個這樣的Buttons 一種是將Command綁定到RelayCommand實現,另一種是綁定到DelegateCommand的 Prism 實現

<Button Command="{Binding DelegateSaveCommand}"/>
<Button Command="{Binding RelaySaveCommand}"/>

ViewModel ICommands

DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate);
RelaySaveCommand = new RelayCommand(param => Save(), param => CanSaveRelay);

CanExecute方法/謂詞

public bool CanSaveDelegate()
{
    return HasChanges;
}
public bool CanSaveRelay
{
    get { return HasChanges; }
}

兩者都使用屬性HasChanges HasChanges更新時,只有CanSaveRelay更新。 這是應該的方式嗎?

正如已經提到的,這是DelagateCommand預期行為,而不是錯誤。 DelegateCommand不會自動引發CanExecuteChanged事件,您必須在適當的時候通過調用RaiseCanExecuteChanged手動引發該事件。 RelayCommandCommandManager.RequerySuggested事件上中繼。 每次用戶單擊某處或按下按鈕時都會引發此事件。

因為當它是不是很方便,或者沒有合適的地方調用情況RaiseCanExecuteChanged (如在你的情況下,你必須訂閱PropertyChanged事件的模型等),我已經創建了如下簡單的包裝,確保CanExecute的方法包裝命令在CommandManager.RequerySuggested事件上自動執行:

public class AutoCanExecuteCommandWrapper : ICommand
{
    public ICommand WrappedCommand { get; private set; }

    public AutoCanExecuteCommandWrapper(ICommand wrappedCommand)
    {
        if (wrappedCommand == null) 
        {
            throw new ArgumentNullException("wrappedCommand");
        }

        WrappedCommand = wrappedCommand;
    }

    public void Execute(object parameter)
    {
        WrappedCommand.Execute(parameter);
    }

    public bool CanExecute(object parameter)
    {
        return WrappedCommand.CanExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

你可以這樣使用它:

DelegateSaveCommand = new AutoCanExecuteCommandWrapper(new DelegateCommand(Save, CanSaveDelegate));

如果你想堅持DelegateCommand你可以使用ObservesCanExecute

DelegateSaveCommand = new DelegateCommand(Save, CanSaveDelegate).ObservesCanExecute(CanSaveDelegate);

請注意,也有ObservesProperty可用,如果你正在使用您的CanExecute檢查屬性。 但隨后您的財產必須調用 NotifyPropertyChanged。

Prism 提供的 DelegateCommand 中有一個錯誤,它不會引發 CanExecute 事件。 我把頭靠在牆上一天,直到我深入到 Prism 框架提供的DelegateCommand類。 我沒有代碼,但我可以稍后發布我的解決方案。

另一種方法是使用其他 RelayCommand 框架之一。

編輯
除了重新發布代碼之外,還有其他提供解決方案的 SO 問題:

並且 Kent B. 有一篇很好的文章: MVVM Infrastructure: DelegateCommand

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM