2012-02-18 88 views
0

我試圖創建一個綁定到按鈕的命令,並且依賴於viewmodels的層次結構來表示wp7應用程序中的樞軸和pivotitems。它是這樣的(我會忽略儘可能多的樣板代碼可能):RelayCommand not firing CanExecute

父視圖模型:

public RelayCommand RefreshCommand 
    { 
     get 
     { 
      return _refreshCommand; 
     } 

     set 
     { 
      if (_refreshCommand == value) 
      { 
       return; 
      } 

      var oldValue = _refreshCommand; 
      _refreshCommand = value; 

      // Update bindings, no broadcast 
      RaisePropertyChanged(RefreshCommandPropertyName); 
     } 
    } 


    public RelayCommand<RoutedEventArgs> LoadedCommand 
    { 
     get 
     { 
      Action<RoutedEventArgs> getCurrentViewmodel = (args) => 
      { 
       CurrentViewModel = SearchByLocationViewModel; // maybe something better... 
       RefreshCommand = CurrentViewModel.RefreshResultsCommand; 
       RefreshCommand.RaiseCanExecuteChanged(); 
      }; 
      return new RelayCommand<RoutedEventArgs>(getCurrentViewmodel); 
     } 
    } 

    public RelayCommand<SelectionChangedEventArgs> PivotItemChangedCommand 
    { 
     get 
     { 
      Action<SelectionChangedEventArgs> pivotChanged = (args) => 
      { 
       if (args != null) 
       { 
        // update current viewmodel 
        CurrentViewModel = ((Microsoft.Phone.Controls.PivotItem) args.AddedItems[0]).DataContext as ISearchViewModelBase; 
        RefreshCommand = CurrentViewModel.RefreshResultsCommand; 
       } 
      }; 
      return new RelayCommand<SelectionChangedEventArgs>(pivotChanged); 
     } 
    } 

所以,我父視圖模型RefreshCommand屬性設置爲每次子命令它會加載,而且我在選定的透視圖變化時也會這樣做。

的XAML

<Button Command="{Binding RefreshCommand}" /> 

子視圖模型

public Func<bool> CanRefresh 
{ 
    get { return() => !IsLoading; } 
} 

private RelayCommand refreshResultsCommand; 

public RelayCommand RefreshResultsCommand 
{ 
    get 
    { 
     Action doRefresh =() => 
     { 
      SearchResults.Clear(); 
      this._pageNumber = 0; 
      AddItems(); 
     }; 
     return refreshResultsCommand = refreshResultsCommand ?? new RelayCommand(doRefresh, CanRefresh); 
    } 
} 

會發生什麼情況是,該CanRefresh永遠不會被調用。這些命令可以正常工作,具體取決於它調用一個AddItems(這是在每個子視圖模型中實現的虛擬方法)或另一個,但它就像CanExecute永遠不會引發。我正在使用MVVM Light工具包。 謝謝!

+0

當你說'CanRefresh從不叫'時,你的意思是'CanRefresh'屬性還是其中的lambda?你怎麼知道它從來沒有被稱爲? – 2012-02-18 18:01:22

回答

0

那麼您每次打電話給LoadedCommandPivotChangedComman屬性時都會創建一個新的中繼命令。由於SL/WPF經常調用這些屬性,所以必須確保每次調用屬性時都不要創建命令。其實你的RefreshResultsCommand實現正確的模式。

確保正確實施屬性/命令的最佳方法是使用Laurent's MVVM snippets。將它們下載到您的代碼片段目錄並使用它們。除了始終生產相同的樣板代碼並因此提高質量外,他們還大大加快了速度!您也可以use the installer安裝片段。

1

我懷疑是從來沒有被調用的方法CanExecute因爲永遠不會被該視圖-層當前綁定到視圖模型對象上燒製RelayCommandCanExecuteChanged事件。由於您在大多數屬性訪問中創建了命令,因此有很多命令可以使用,並且很有可能您將事件觸發到尚未被視圖層綁定的命令或者不是更長的時間。

我從來沒有見過任何人在每次調用屬性getter時都會創建新的命令。你可以嘗試在構造函數中創建一次命令,而不是在每次訪問屬性時查看是否修復了這些問題?

+0

看看代碼示例,我AM調用該方法..... – 2012-02-18 17:49:07

+0

@DanielPerez:您的確在調用'RaiseCanExecuteChanged'方法,抱歉沒有注意到它。但它隱藏得很好。我已經更新了我的答案。 – 2012-02-18 18:30:16