![](/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.