Search code examples
mvvmviewviewmodelscreenshotmvvm-light

How to call a function(which works with UIElements) in View from ViewModel using MVVM pattern


I'm using MVVM Light Toolkit and in my View, I have a function that takes a screenshot and returns byte array of that screenshot. Since taking an screenshot (using UIElements) is related to view not ViewModel.

byte[] TakeScreenShot(Canvas sourceUiElement)    

I need to get the return value of the function in my ViewModel but I can't come up with a proper way of doing it.

I other hand if I wanted to do move this function to my ViewModel, I need to have access to that element in view but without referencing the View in my ViewModel (maybe as argument or something to a Command?)


Solution

  • Since this question is tagged as MvvmLight, then here is an MvvmLight Toolkit answer. Use said toolkit's Messenger class. Simply define the following message classes somewhere in your application:

    public class TakeScreenshotMessage : MessageBase { }
    public class ScreenshotTakenMessage : GenericMessage<byte[]>
    {
        public ScreenshotTakenMessage (byte[]content) : base(content) { }
        public ScreenshotTakenMessage (object sender, byte[]content) : base(sender, content) { }
        public ScreenshotTakenMessage (object sender, object target, byte[]content) : base(sender, target, content) { }
    }
    

    In your code-behind's constructor, register for the TakeScreenshotMessage like this:

    Messenger.Default.Register<TakeScreenshotMessage>(this, (msg) =>
    {
        byte[] bytes = this.TakeScreenShot(someCanvas);
        Messenger.Default.Send(new ScreenshotTakenMessage(bytes));
    });
    

    And in your view model, register for the ScreenshotTakenMessage like this:

    Messenger.Default.Register<ScreenshotTakenMessage>(this, (msg) =>
    {
        byte[] bytes = msg.Content.
        //do something with your bytes
    });
    

    Now you can take a screen shot at any time simply by calling the following from anywhere in your application (i.e. view models, views, helper classes, etc.):

    Messenger.Default.Send(new TakeScreenshotMessage());