Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commanding in MVVM (WPF)--how to return a value?

Tags:

c#

mvvm

wpf

I've been using MVVM pattern for a while now, but I still run into problems in real-life situations. Here's another one: I use commanding and bubble up the event to be handled in the ViewModel. So far, so good. But the project for which I'm using MVVM is actually a class library. Once I run the command code, I need to be able to send an object back to the calling application. What are suggested ways to do so?

Specifically: In my calling app I have a XAML page bound directly to the library's ViewModel, which contains an object "Thing1". When a button is clicked, a method in the ViewModel is called (call it "CopyThing1()"). It copies "Thing1" to create "Thing2". Then I need to send "Thing2" back to the calling app.

Thanks!!!

like image 889
ml_black Avatar asked Feb 10 '10 20:02

ml_black


2 Answers

The ideal approach is to define a new class inherited from ICommand as follows:

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);
    }
}

Note that Execute2 returns the value just like a normal function. Here is how to use it.

    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;
    }

Calls Execute2 instead of Execute will returns the value.

like image 72
Wayne Lo Avatar answered Oct 02 '22 08:10

Wayne Lo


If Thing2 is another property on your viewmodel, you can use normal INotifyPropertyChanged to inform the UI of the change.

You could also use Prism's EventAggregator for a more decoupled approach

like image 34
kenwarner Avatar answered Oct 02 '22 10:10

kenwarner