I recently started using WPF and the MVVM framework, one thing that I have wanted to do is to have a type safe implementation of ICommand
so I do not have to cast all the command paramaters.
Does anyone know of a way to do this?
Not using that syntax, as you probably found:
error CS0701: ``System.Func`' is not a valid constraint. A constraint must be an interface, a non-sealed class or a type parameter
Your best bet is to encapsulate the
Func<E,bool>
semantics in an interface, like:
interface IFunctor<E> { bool Execute(E value); }
and then use this interface in the class definition.
Although, I am wondering what you're looking to accomplish as there may be another approach to your problem.
Per the comment that @Alex is looking for a strongly typed ICommand
implementation :
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);
}
}
Used like so:
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>
I would recommend using Microsoft's DelegateCommand or RelayCommand , or any other implementation of either of these.
Your command class should subscribe to ICommand and define the CanExecuteChanged as below.
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.