【问题标题】:Button IsEnabled state not updating based on CanExecute return value按钮 IsEnabled 状态未根据 CanExecute 返回值更新
【发布时间】:2015-08-19 11:33:46
【问题描述】:

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

一旦用户从组合框中选择了一个项目(绑定到一个属性),就会调用 .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 更改调用,所以我怀疑它有什么需要这样做,但这超出了我自学的知识范围。

【问题讨论】:

  • 你有没有尝试在RelayCommand中实现INotifyPropertyChanged
  • @Romasz - 我明白这个建议背后的想法,但我不确定如何修改类来这样做。我认为这不像删除 ReadOnly 修饰符并添加支持的属性那么简单,因为我需要在某处实际设置该属性......你能提供一些指导吗?

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


【解决方案1】:

尝试实现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

【讨论】:

    猜你喜欢
    • 2014-06-26
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 2015-06-10
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多