Reputation: 2160
I am trying to implement a MVVM architecture in my WPF application, and I want to be able to modify the model after executing a command. Note that I am not using any kind of MVVM framework.
I've got a base Command class as follows:
namespace MyApplication.Commands {
public abstract class CommandBase : ICommand {
protected static BackgroundWorker Worker = new BackgroundWorker();
protected static string _result;
public string Result {
get {
return _result;
}
set {
_result = value;
}
}
public abstract void DoWork(DoWorkEventArgs args);
public virtual void Execute(object parameter) {
Worker = new BackgroundWorker();
Worker.DoWork += (o, args) => DoWork(args);
Worker.RunWorkerCompleted += (sender, args) => {
RaiseCanExecuteChanged(EventArgs.Empty);
};
Worker.ProgressChanged += (sender, args) => {
RaiseCanExecuteChanged(EventArgs.Empty);
};
Worker.WorkerReportsProgress = true;
Worker.RunWorkerAsync(parameter);
}
public virtual bool CanExecute(object parameter) {
return !Worker.IsBusy;
}
public event EventHandler CanExecuteChanged;
protected virtual void RaiseCanExecuteChanged(EventArgs e) {
CanExecuteChanged(this, e);
}
}
}
I've got my actual command which implements this, as follows:
namespace MyApplication.Commands {
internal class DoSomethingCommand : CommandBase {
public override void DoWork(DoWorkEventArgs args) {
Worker.ReportProgress(0);
var success = false;
try {
var parameter = args.Argument as int?;
success = DoSomething(parameter);
} finally {
args.Result = success;
}
}
private static bool DoSomething(int parameter) {
// Do something expensive here...
System.Func func = (arg) => {
Thread.Sleep(arg);
return true;
};
// etc etc...
var success = func.Invoke(parameter);
return success;
}
}
}
I'm using this as a way to perform expensive operations while still maintaining the MVVM model. I had to perform RaiseCanExecuteChanged
in the progress and completion events, otherwise the UI will not update the corresponding button state.
However, now I want to modify a property of the current Model
being accessed (AKA selected in a ListView
control), which is exposed as a property of the ViewModel
. How can I do this while still maintaining the MVVM architecture?
Also is there any better way of passing the current state of the ViewModel
to my commands? Currently, I'm using a MultiBinding
plus an IMultiValueConverter
that just allows passing an object[]
.
Upvotes: 0
Views: 267
Reputation: 1401
Why not passing a reference to your viewModel in the constructor of your command and and hold it locally in a field. That way you should be able to manipulate the whole viewModel using its exposed methods and properties.
Regarding your second question:
Also is there any better way of passing the current state of the ViewModel to my commands?
Your command should be implemented in the viewModel so you shouldn't have to provide the viewModel's state. If that's not the case why not just pass in the whole viewModel by passing DataContext
in the CommandParameter
property of the control.
Upvotes: 1