1

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?

2 Answers 2

2

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));
}
6
  • The implementation is completely irrelevant to the question I am asking and I have not asked anything about Dependency Injection or the implementation of actually taking a screenshot. It is just a basic example of my work flow, Could you please read the entire question before commenting as my question relates to implementing generic/reusable method within MVVM without implementing them like POCO objects / models
    – Johnny
    Commented Oct 15, 2018 at 9:34
  • edited to match your edits, but its still essentially the same answer. Don't use a global variable and dont instanciate the class in the viewmodel. Pass it in as a dependency
    – Ewan
    Commented Oct 15, 2018 at 9:50
  • Sorry bare with me i'm still quite confused and may be due to my lack of knowledge of DI. From what I can see in your example you have a ViewModel that passes the ICapture Interface to the VM's constructor maybe via DI then a method to call the screenshot method which is binded to an element on screen, so the mystery to me is where does this.captureService.CaptureShot(); get implemented, its defined in the interface, call in the ViewModel but where is it implemented ??
    – Johnny
    Commented Oct 15, 2018 at 10:00
  • I thought you said the implementation was unimportant?
    – Ewan
    Commented Oct 15, 2018 at 10:03
  • I know but the location of the implementation is everything
    – Johnny
    Commented Oct 15, 2018 at 10:06
1

Personally, the way I organise my MVVM projects is to have the model layer classes only hold data. (Usually this is more specifically data that will be persisted to some kind of data store).

Anything else is held within the ViewModel layer, with functionality either coded directly as part of that class, or injected as an external service.

So in your case, I'd have an ICapture service implementation injected into the MainViewModel where the CaptureMethod() returns an instance of a CaptureModel class, rather than being a void method.

5
  • Amazingly clear, thank you for such a simple explanation. So I now have an additional folder called Services. In there I have a CaptureClass that Inherits from ICapture. Then I will use dependency injection to provide that service class to the view models constructor so that I can then utilise all of the methods from that single service class. Awesome thank you so much.
    – Johnny
    Commented Oct 15, 2018 at 10:09
  • don't put CaptureService in the same project as the Application. It makes the interface pointless
    – Ewan
    Commented Oct 15, 2018 at 10:12
  • Portable Class Library Then ? Reason for the interface currently is because its Xamarin and need the interface so that I can implement platform specific services
    – Johnny
    Commented Oct 15, 2018 at 10:16
  • @Ewan Why not allow two or more different implementations of the ICaptureService interface (within the application) and determine at runtime which to use. Or to have a solid implementation for the application, and a different mock implementation for unit tests (perhaps in different projects but within the same application solution).
    – Peregrine
    Commented Oct 15, 2018 at 10:17
  • if its Xamarin, then you can do an implementation in each native project and have the interface in a PCL yes.
    – Ewan
    Commented Oct 15, 2018 at 10:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.