繁体   English   中英

CanExecute()返回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实现:

http://codepaste.net/ho9s5a

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM