Reputation: 1574
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
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
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