![](/img/trans.png)
[英]Button disabled although ICommand.CanExecute evaluates to true
[英]CanExecute() returns true and button is still disabled
我在Windows Phone特定頁面中有一個BottomAppBar.AppBarButton
,它綁定到中繼命令。 代碼,綁定和viewmodel的實現在項目的其他頁面上都以基本上相同的方式使用,並且完全按預期運行。
在這種特定情況下的問題是,即使在提高.RaiseCanExecuteChanged()
方法之后,按鈕仍保持禁用狀態,並且CanExecute()
返回true
。
我原本以為這可能是由於過多的調用而導致的,這些調用是通過手動更改屬性更改來手動引發通知的,所以收緊了我那部分代碼,以便僅在需要時以及在需要更改按鈕狀態時才引發該方法。 即使CanExecute()
返回true
,按鈕仍保持禁用CanExecute()
。 如果我注釋掉CanExecute()
所有檢查並將其默認設置為true,則該按鈕將按預期啟用,並且在點RelayCommand
會觸發預期的Execute()
函數,因此似乎可以執行RelayCommand
的初始化。 如果我然后放回檢查,並在每次觸發CanExecute()
時CanExecute()
,則當它返回true時,該按鈕不會啟用。
有任何想法嗎? 對於它的價值,我在下面添加了代碼,但我不認為這是原因。
RelayCommand
類是VS中HubApp隨附的標准類,因此我將省略該代碼。
viewmodel構造函數的最后一行是RelayCommand;
AddStrikeTeamCommand = new RelayCommand(async() => await AddStrikeTeam(), CanAddStrikeTeam);
可以添加是;
private bool CanAddStrikeTeam()
{
//if (NameWorking == string.Empty) return false;
//if (FactionWorking == string.Empty) return false;
//if (PointsLimitWorking < 1) return false;
//if (!IsValidTeamWorking) return false;
return true;
}
最后,按鈕綁定
<AppBarButton x:Name="accept" Icon="Accept" Label="accept"
Command="{Binding AddStrikeTeamCommand}"/>
我可能打賭您的問題與RaiseCanExecuteChanged()有關。 如果您習慣使用WPF及其如何為您自動刷新CanExecute,則尤其如此。 查看此Delegate Command實現:
ICommand
接口定義事件CanExecuteChanged
,該事件指示按鈕(或UI元素)刷新其“ Enabled
狀態。 在WPF中,這是由靜態命令管理器不斷提出的。 在WinRT中不存在。 在WPF中,由於它頻繁出現,因此WPF開發人員必須注意CanExecute()
不是昂貴的操作。 WinRT提供了昂貴的測試,但因此要求開發人員手動引發事件。 我希望這是有道理的。
我處理此問題的一種方法是:
DelegateCommand _SaveCommand = null;
public DelegateCommand SaveCommand
{
get
{
if (_SaveCommand != null)
return _SaveCommand;
_SaveCommand = new DelegateCommand
(
() =>
{
// TODO
},
() => true
);
this.PropertyChanged += (s, e) => _SaveCommand.RaiseCanExecuteChanged();
return _SaveCommand;
}
}
這基本上是基於(通常在我的View模型中)任何屬性的更改刷新CanExecute的。 如果您對ObservableCollection中的模型進行了潛在的更改,這還不夠,但這是整個過程的一個很好的開始。
您可能根本沒有這個問題。 而且您正在打電話提出該事件,該事件返回true,並且仍然無法正常工作。 如果正在發生這種情況,那么它就必須是您的代碼,因為Commands正在為數千個應用程序工作。 但是,如果您想將代碼發送給我,我會看一下。
祝你好運!
我知道這是一個較晚的答案,但此帖子已鏈接到另一個問題,因此我覺得我應該發布一個更好的代碼示例。
傑里的答案很可能是正確的,問題是在該ICommand實現中不會自動引發RaiseCanExecuteChanged
,但是提供的代碼示例重新引入了導致該錯誤首先出現的相同問題-每當有問題時,它都會引發CanExecuteChanged屬性更改,導致CanExecute的調用遠遠超出了必要。
PropertyChanged事件處理程序應包括一個檢查,並且如果更改的屬性是CanExecute中使用的屬性,則僅引發CanExecuteChanged。
由於您的CanExecute是
private bool CanAddStrikeTeam()
{
if (NameWorking == string.Empty) return false;
if (FactionWorking == string.Empty) return false;
if (PointsLimitWorking < 1) return false;
if (!IsValidTeamWorking) return false;
return true;
}
那么事件處理程序僅在屬性之一更改時才需要引發CanExecuteChanged
this.PropertyChanged += (s, e) =>
{
switch (e.PropertyName)
{
case "NameWorking":
case "FactionWorking":
case "PointsLimitWorking":
case "IsValidTeamWorking":
AddStrikeTeamCommand.RaiseCanExecuteChanged();
break;
}
}
如果使用的是Mvvm Light,請確保包含GalaSoft.MvvmLight.CommandWpf命名空間,而不是GalaSoft.MvvmLight.Command命名空間。 (請參閱有關MVVM RelayCommand CanExecute的第二個答案)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.