我最近开始使用WPF和MVVM框架,我想做的一件事就是拥有ICommand
的类型安全实现,所以我不必抛出所有的命令参数。
有谁知道这样做的方法?
答案 0 :(得分:14)
不使用该语法,正如您可能找到的那样:
错误CS0701:``System.Func`'不是有效约束。约束必须是接口,非密封类或类型参数
最好的办法是将 Func<E,bool>
语义封装在界面中,例如:
interface IFunctor<E>
{
bool Execute(E value);
}
然后在类定义中使用此接口。虽然,我想知道你想要完成什么,因为可能有另一种方法解决你的问题。
根据@Alex正在寻找强类型ICommand
实施的评论:
public FuncCommand<TParameter> : Command
{
private Predicate<TParameter> canExecute;
private Action<TParameter> execute;
public FuncCommand(Predicate<TParameter> canExecute, Action<TParameter> execute)
{
this.canExecute = canExecute;
this.execute = execute;
}
public override bool CanExecute(object parameter)
{
if (this.canExecute == null) return true;
return this.canExecute((TParameter)parameter);
}
public override void Execute(object parameter)
{
this.execute((TParameter)parameter);
}
}
像这样使用:
public class OtherViewModel : ViewModelBase
{
public string Name { get; set; }
public OtherViewModel(string name) { this.Name = name; }
}
public class MyViewModel : ViewModelBase
{
public ObservableCollection<OtherViewModel> Items { get; private set; }
public ICommand AddCommand { get; private set; }
public ICommand RemoveCommand { get; private set; }
public MyViewModel()
{
this.Items = new ObservableCollection<OtherViewModel>();
this.AddCommand = new FuncCommand<string>(
(name) => !String.IsNullOrEmpty(name),
(name) => this.Items.Add(new OtherViewModel(name)));
this.RemoveCommand = new FuncCommand<OtherViewModel>(
(vm) => vm != null,
(vm) => this.Items.Remove(vm));
}
}
XAML:
<ListBox x:Name="Items" ItemsSource="{Binding Items}" />
<Button Content="Remove"
Command="{Binding RemoveCommand}"
CommandParameter="{Binding SelectedItem, ElementName=Items}" />
<StackPanel Orientation="Horizontal">
<TextBox x:Name="NewName" />
<Button Content="Add"
Command="{Binding AddCommand}"
CommandParameter="{Binding Text, ElementName=NewName}" />
</StackPanel>
我建议使用Microsoft的DelegateCommand或RelayCommand,或其中任何一种的任何其他实现。
答案 1 :(得分:1)
您的命令类应订阅ICommand并定义CanExecuteChanged,如下所示。
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}