我在Windows Phone特定页面中有一个BottomAppBar.AppBarButton
,它绑定到一个中继命令。代码,绑定和视图模型实现在项目的其他页面上基本上以相同的方式使用,并且完全按预期工作。
此特定情况下的问题是即使提升.RaiseCanExecuteChanged()
方法后按钮仍处于停用状态,CanExecute()
会返回true
。
我原本以为这可能是由于过多调用手动提升属性更改的通知,因此收紧了我的代码部分,以便只根据需要引发方法,并在需要更改按钮的时候状态。即便如此,尽管CanExecute()
返回true
,该按钮仍处于停用状态。
如果我注释掉CanExecute()
中的所有检查并且默认为true,则按钮按预期启用,并且当点击时触发预期的Execute()
函数,因此看起来{{1}的初始化好的如果我然后让检查重新进入,并在每次RelayCommand
被触发时逐步执行,当它返回true时,该按钮不会被启用。
有什么想法吗?为了它的价值,我在下面添加了代码,但我不认为这是原因。
CanExecute()
类是VS中HubApp附带的标准类,因此我将省略该代码。
viewmodel构造函数的最后一行是RelayCommand;
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;
}
答案 0 :(得分:2)
我可能打赌你的问题与RaiseCanExecuteChanged()有关。如果您习惯WPF以及它如何为您自动刷新CanExe4cute,则尤其如此。查看此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中的模型中有潜在的变化,这是不够的,但它对整个事情来说是个不错的开始。
您可能根本没有遇到此问题。并且你要召集事件,它返回真实,仍然无法正常工作。如果这就是正在发生的事情,它只需要是您的代码,因为命令适用于数千个应用程序。但是,如果你想把你的代码发给我,我会看看。
祝你好运!
答案 1 :(得分:1)
我知道这是一个迟到的答案,但这篇文章在另一个问题中被链接,所以我觉得我应该发布一个更好的代码示例。
Jerry's answer很可能是正确的,问题是RaiseCanExecuteChanged
在ICommand的实现中没有自动引发,但提供的代码示例重新引入了导致它被取出的完全相同的问题首先 - 只要任何属性发生变化,它就会引发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;
}
}
答案 2 :(得分:0)
如果您使用的是Mvvm Light,请确保包含GalaSoft.MvvmLight.CommandWpf命名空间而不是GalaSoft.MvvmLight.Command命名空间。 (见MVVM RelayCommand CanExecute上的第二个答案)