Общая / безопасная для типов реализация ICommand? - PullRequest
11 голосов
/ 08 июня 2011

Я недавно начал использовать WPF и инфраструктуру MVVM, одну вещь, которую я хотел сделать, это иметь безопасную реализацию типа ICommand, поэтому мне не нужно приводить все параметры команды.

Кто-нибудь знает способ сделать это?

Ответы [ 2 ]

14 голосов
/ 08 июня 2011

Не используется этот синтаксис, как вы, вероятно, нашли:

ошибка 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>

Я бы порекомендовал использовать DelegateCommand от Microsoft или RelayCommand или любую другую реализацию любого из них.

1 голос
/ 22 сентября 2016

Ваш командный класс должен подписаться на ICommand и определить CanExecuteChanged, как показано ниже.

public event EventHandler CanExecuteChanged
{
      add { CommandManager.RequerySuggested += value; }
      remove { CommandManager.RequerySuggested -= value; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...