Buck Hicks
Buck Hicks

Reputation: 1574

Passing a variable to a second window using MVVMLight?

I am building an application to teach myself MVVM and with some Googling (and some trial an error) I have managed to get to the point where I can open a second window from the ViewModel but not to pass a variable from one page to the other. This is my ViewModel.

    public VendorSelectViewModel()
    {
        Ping ping = new Ping();
        PingReply pingresult = ping.Send("192.168.1.10");
        if (pingresult.Status.ToString() == "Success")
        {
            LoadVendorsAsync();
        }
        else
        {
            LoadVendors();
        }

        NextCommand = new RelayCommand(NextWindow);
    }

    public ICommand NextCommand { get; private set; }

    void NextWindow()
    {
        Console.WriteLine(selectedVendor.VendorName); 
        Messenger.Default.Send(new NotificationMessage("NextWindow"));
    }

In my view I have this

    public VendorSelectWindow()
    {
        InitializeComponent();
        _vm = new Biz.Invoicer.VendorSelectViewModel();
        DataContext = _vm;

        Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
    }

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        if (msg.Notification == "NextWindow")
        {
            var invoicerWindow = new InvoicerWindow();
            invoicerWindow.Show();
        }
    }

So I know (or I think I know) this may not be a "Best Practice" but I will come back to this and refactor as I get to know the MVVM patern and MVVM Light better. Currently I am trying to pass a variable from the ViewModel of the first page (VendorSelectViewModel) to the Second page (InvoicerWindow) but I haven't managed to the syntax correct.

What do I need to do to pass a variable from one page to the next?

Upvotes: 1

Views: 309

Answers (2)

mm8
mm8

Reputation: 169420

Instead of passing a NotificationMessage to the messenger, you could pass an instance of your own custom type which may carry as many values you want:

void NextWindow()
{
    Console.WriteLine(selectedVendor.VendorName); 
    Messenger.Default.Send(new YourPayload() {WindowName = "NextWindow", Parameter = "some value..:");
}
...

public VendorSelectWindow()
{
    InitializeComponent();
    _vm = new Biz.Invoicer.VendorSelectViewModel();
    DataContext = _vm;

    Messenger.Default.Register<YourPayload>(this, NotificationMessageReceived);
}

private void NotificationMessageReceived(YourPayload msg)
{
    if (msg.WindowName == "NextWindow")
    {
        string param = msg.Parameter;
        var invoicerWindow = new InvoicerWindow();
        invoicerWindow.Show();
    }
}

YourPayload is a custom class with two properties, WindowName and Parameter.

Upvotes: 1

Grx70
Grx70

Reputation: 10359

First of all you can pass an arbitrary object as the parameter of the IMessenger.Send<TMessage> method - the TMessage type parameter is not restricted. E.g.:

//ViewModel:
void NextWindow()
{
    //...
    int someValue = 10;
    Messenger.Default.Send(someValue);
}

//View:
public VendorSelectWindow()
{
    //...
    Messenger.Default.Register<int>(this, MessageReceived);
}

private void MessageReceived(int value)
{
    //...
}

If however you find the NotificationMessage class particularly useful in your case you could make use of the generic NotificationMessage<T> version, which exposes additional property Content of arbitrary type T:

//ViewModel:
void NextWindow()
{
    //...
    int someValue = 10;
    Messenger.Default.Send(new NotificationMessage<int>(someValue, "Notification text"));
}

//View:
public VendorSelectWindow()
{
    //...
    Messenger.Default.Register<NotificationMessage<int>>(this, MessageReceived);
}

private void MessageReceived(NotificationMessage<int> message)
{
    var someValue = message.Content;
    //...
}

Or, if that does not suit you, you could create your own class deriving from NotificationMessage and exposing additional members and use that as the message object.

Upvotes: 2

Related Questions