Командование в MVVM (WPF)--как вернуть значение?

Я использую шаблон MVVM уже некоторое время, но я все еще сталкиваюсь с проблемами в реальных ситуациях. Вот еще один: Я использую командование и пузырь вверх событие, которое будет обрабатываться в ViewModel. Пока все идет хорошо. Но проект, для которого я использую MVVM, на самом деле является библиотекой классов. После запуска кода команды мне нужно иметь возможность отправить объект обратно в вызывающее приложение. Какие предлагаются способы сделать это?

специально: В мое призвание приложение на XAML страница, привязанная непосредственно к ViewModel библиотеки, которая содержит объект "Thing1". При нажатии кнопки вызывается метод в ViewModel (назовите его "CopyThing1()"). Он копирует "Thing1" создать "Thing2". Затем мне нужно отправить "Thing2" обратно в вызывающее приложение.

спасибо!!!

4 ответов


команды не возвращают значения, они изменяют состояние приложения. В случае ICommands, прикрепленных к ViewModels, это довольно просто, потому что вы можете сделать это, просто изменив ViewModel при выполнении команды.

использование RelayCommand от отличная статья MVVM Джоша Смита:

public class MyViewModel : INotifyPropertyChanged
{
    private readonly ICommand mutateCommand;
    private Thing thing;

    public MyViewModel()
    {
        this.mutateCommand = new RelayCommand(this.Mutate);
    }

    public ICommand MutateCommand
    {
        get { return this.mutateCommand; }
    }

    public Thing Thing
    {
        get { return this.thing; }
        set
        {
            this.thing = value;
            // raise PropertyChanged event here...
        }
    }

    private void Mutate(object parameter)
    {
        this.Thing = new Thing();
    }
}

после вызова myVM.MutateCommand.Execute(new object()); вы можете получить доступ к новому значению myVM.Thing.


Если Thing2 является другим свойством viewmodel, вы можете использовать normal INotifyPropertyChanged для информирования пользовательского интерфейса об изменении.

вы также можете использовать Присм ' s EventAggregator для более развязанного подхода


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


идеальным подходом является определение нового класса, унаследованного от ICommand следующим образом:

public abstract class Command2<T1, T2> : ICommand {
    public abstract T2 Execute2(T1 parameter);
}

public class DelegateCommand2<T1, T2> : Command2<T1, T2> {
    public DelegateCommand2(Func<T1, T2> execute, Predicate<T1> canExecute) {
        _execute = execute;
        _canExecute = canExecute;
    }

    public override T2 Execute2(T1 parameter) {
        if (CanExecute(parameter) == false)
            return default(T2);
        else
            return _execute((T1)parameter);
    }
}

обратите внимание, что Execute2 возвращает значение так же, как обычная функция. Вот как его использовать.

    private readonly ICommand _commandExample = new DelegateCommand2<int, Point3D>(
        commandExample_Executed,
        commandExample_CanExecute
    );

    public Command2<int, Point_3D> CommandExample {
        get {
            return (Command2<int, Point_3D>) _commandExample;
        }
    }

    private static Point3D commandExample_Executed(int index) {
        return Fun1(index); //Fun1 returns a Point_3D
    }

    private static bool commandExample_CanExecute(int index) {
        return true;
    }

вызывает Execute2 вместо Execute возвращает значение.