【发布时间】: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