C# MVVM – How to Implement a General Method Across Several View Models

Architecturecmvvmsoftware

Currently I have implemented a method in to a model to take a screen shot like so E.G.

Interface

public interface ICapture {
 void CaptureMethod();
}

This is the model that implements that interface

public class CaptureModel : ICapture {
    void CaptureMethod(){ //implement the code to take screen shot }
}

Now I want to execute a screen shot on one or multiple view models, so I would need to instantiate the and call the function like so.

public ViewModel(){
 void TakeScreenShotMethodOrCommandDontCare(){
   ICapture captureClass = new CaptureClass();
   captureClass.captureMethod
  }
}

Which just feels WRONG having to instantiate an instance of an object in order to call a function which will be taking a screenshot.

I suppose i could go in the view model and have capture screenshot method but that would lead to code duplication across all view models with that feature.

Maybe a static utility class but surely that would be expensive on the app.

I feel if I had an interface that was implemented by a base class then my view model could inherit from that base class and implement the base implementation on any view model I desire.

So to sum up my question, if you wanted to implement a method that captures screen shots and you like mvvm then where would you implement?

Best Answer

Your code should look like this:

public class CaptureViewModel 
{
    ICapture captureService
    public CaptureViewModel(ICapture captureService) 
    {
        this.captureService = captureService
    }

    //bind this to the View
    public void TakeScreenShotCommand()
    {
        this.captureService.CaptureShot();
    }
}

The ICapture implementation is Instantiated in the DI container with the desired lifecycle and injected into the ViewModel. Allowing you to reuse the code across all ViewModels

captureService is implemented in a library class somewhere.

public class CaptureService : ICapture
{
     public void CaptureShot() {...implementation code here }
}

your DI Container or startup class looks like

public void Main()
{
    var container = new DiContainerOfChoice();
    container.Register<ICapture>(new CaptureService());

    MainView = container.Resolve<MyView>();
    // view requires ViewModel which requires CaptureService, DI sorts it all out for you

    //poor mans DI
    var cs = new CaptureService(); //keep hold of this to pass into other view models
    MainView = new View(new Viewmodel(cs));
}