好的,XAML非常简单,并使用MVVM绑定到ICommand SomeCommand { get; }视图模型上的属性:
<Button Command="{Binding Path=SomeCommand}">Something</Button>
Run Code Online (Sandbox Code Playgroud)
如果SomeCommand返回null,则启用该按钮.(与CanExecute(object param)方法无关ICommand,因为没有实例可以调用该方法)
现在的问题是:为什么启用按钮?你会怎么做?
如果按"启用"按钮,显然没有任何调用.按钮看起来很有用,这很丑陋.
它已启用,因为这是默认状态.自动禁用它将是一种导致其他问题的任意措施.
如果要禁用没有关联命令的按钮,请将IsEnabled属性绑定到SomeCommand使用适当的转换器,例如:
[ValueConversion(typeof(object), typeof(bool))]
public class NullToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value !== null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Run Code Online (Sandbox Code Playgroud)
我的同事找到了一个不错的解决方案:使用具有约束力的后备值!
public class NullCommand : ICommand
{
private static readonly Lazy<NullCommand> _instance = new Lazy<NullCommand>(() => new NullCommand());
private NullCommand()
{
}
public event EventHandler CanExecuteChanged;
public static ICommand Instance
{
get { return _instance.Value; }
}
public void Execute(object parameter)
{
throw new InvalidOperationException("NullCommand cannot be executed");
}
public bool CanExecute(object parameter)
{
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
然后XAML看起来像:
<Button Command="{Binding Path=SomeCommand, FallbackValue={x:Static local:NullCommand.Instance}}">Something</Button>
Run Code Online (Sandbox Code Playgroud)
此解决方案的优势在于,如果您打破了Demeter定律并且在绑定路径中有一些点(每个实例可能会变成的点),则效果会更好null。
与乔恩的答案非常相似,您可以使用带有触发器的样式来标记在没有命令集时应禁用的按钮。
<Style x:Key="CommandButtonStyle"
TargetType="Button">
<Style.Triggers>
<Trigger Property="Command"
Value="{x:Null}">
<Setter Property="IsEnabled"
Value="False" />
</Trigger>
</Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)
我更喜欢这个解决方案,因为它非常直接地解决问题并且不需要任何新类型。