按钮IsEnabled状态不基于CanExecute返回值更新

时间:2015-08-19 11:33:47

标签: c# xaml windows-runtime windows-phone-8.1

我在Windows 8.1'通用'应用中有一个按钮绑定到RelayCommand,根据CanExecute()的返回值,该按钮未按预期更新为已禁用。  实现细节如下,但基本上,RelayCommand初始化为返回false,更改为按预期启用,但不会按预期返回到禁用状态。

UI流程是用户从组合框中选择一个项目(绑定到属性),调用.RaiseCanExecuteChanged()并返回true,按钮更新为按预期启用。第二个组合框(现在可见)绑定到另一个属性,该属性在更改时运行一个方法来设置验证属性,当更改时调用.RaiseCanExecuteChanged()。这一次,当我希望看到按钮被禁用时,它不是,尽管CanExecute()返回false。有趣的是,如果单击该按钮,则该动作的委托方法不会运行,但我需要禁用该按钮,因为该按钮的click方法为Frame.GoBack()

RelayCommand类:

public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }

    public void RaiseCanExecuteChanged()
    {
        var handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

CanExecute方法:

private bool CanAcceptTransportProfile()
    {
        if (IsTPInEditMode == false) return false;
        if (SelectedTransport == null) return false;
        if (IsSubPropertiesValid == false) return false;
        return true;
    }

初始属性和更改:

public Unit SelectedTransport
    {
        get { return _selectedTransport; }
        set
        {
            if (_selectedTransport != value)
            {
                _selectedTransport = value;
                RaisePropertyChanged("SelectedTransport");
                OnSelectedTransportChange();
            }
        }
    }

private void OnSelectedTransportChange()
    {
        switch (SelectedTransport == null)
        {
            case true:
                IsTransportSelected = false;
                IsUnitsPerTransportValid = true;
                IsSharingWithValid = true;
                IsNestingValid = true;
                break;
            case false:
                IsTransportSelected = true;
                ShowUnitsPerTransportSelector = IsAllowedToShareTransport ? false : true;
                break;
        }
        CommandAcceptTransportProfile.RaiseCanExecuteChanged();
    }

第二次财产变更:

public int UnitsPerTransport
    {
        get { return _unitsPerTransport; }
        set
        {
            if (_unitsPerTransport != value)
            {
                _unitsPerTransport = value;
                RaisePropertyChanged("UnitsPerTransport");
                OnUnitsPerTransportChange();
            }
        }
    }

private void OnUnitsPerTransportChange()
    {
        List<int> unitoptions = UnitHelper.UnitRangeFromSquadSize(this.SquadSize);
        if (!unitoptions.Contains(_unitsPerTransport))
        {
            foreach (int num in unitoptions)
            {
                if (_unitsPerTransport < num)
                {
                    if (num % _unitsPerTransport != 0)
                    { goto Invalid; }
                }
                else
                {
                    if (_unitsPerTransport % num != 0)
                    { goto Invalid; }
                }
            }
            goto Valid;
        }
        else
        { goto Valid; }

    Valid:
        IsUnitsPerTransportValid = true;
        IsSubPropertiesValid = (IsUnitsPerTransportValid && IsNestingValid && IsSharingWithValid && IsTotalUnitsRequiredValid) ? true : false;
    Invalid:
        IsUnitsPerTransportValid = false;
        IsSubPropertiesValid = false;
    }

IsSubPropertiesValid在发生变化时会引发CommandAcceptTransportProfile.RaiseCanExecuteChanged()UnitHelper是一个静态类,只返回ints的列表。然后,该方法从组合框中检查所选的int,并相应地转到有效/无效。当它将IsSubPropertiesValid设置为false时,我希望看到该按钮被禁用,而不是。

我一直在我的项目中以这种方式使用RelayCommand并且它在每个实例中都按预期工作,除了这个,它有更复杂的验证/ Onproperty更改调用围绕它,所以我怀疑它有与此有关,但要解决这个问题超出了我自学的知识。

1 个答案:

答案 0 :(得分:0)

尝试实现 INotifyPropertyChanged ,示例可能如下所示:

public class RelayCommand : ICommand, INotifyPropertyChanged
{
    #region INotify
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaiseCanExecuteChanged()
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, "CanExecute");
        }
    }
    #endregion