views:

66

answers:

2

Hello Stack Overflow! First time poster.

I'm using MVVM-Light with Silverlight 4 and RIA Services. This has been a learning experience! But so far, it's working beautifully. I was wondering two things. Right now, I'm using the Messenger framework to pass EntityObjects back to the ViewModel. For instance, I need to open a View Model with a specific "Course" object. So I instantiate the View, and the View sends a Message to the ViewModel with the Course. I've got a couple questions.

First question: Is this the best way to do this? I don't want to use Prism or Unity or any of those other things because I don't have the time to learn them. (This was, for me, the big draw of MVVM Light. The Light part.) But I couldn't see any other way to pass parameters to the VM Locator.

The second part is, this means I am sending messages from the View to that View's specific ViewModel. My messages look like this:

  Tuple<Models.Course, Services.VWDS> courseDomainContextTuple = new Tuple<Models.Course, Services.VWDS>(Course, DomainContext);

  NotificationMessage<Tuple<Models.Course, Services.VWDS>> message = new NotificationMessage<Tuple<Models.Course, Services.VWDS>>(this, this.DataContext, courseDomainContextTuple, Models.MessageString.EditCourse);

  Messenger.Default.Send<NotificationMessage<Tuple<Models.Course, Services.VWDS>>>(message);  

So, as you can see, I'm bundling the Course and the DomainContext (Ah RIA. Why won't you let me get the Context from the EntityObject?) and sending them to the ViewModel (which is "this.DataContext") - and yes, I know I should make a class for that message.

Here's the problem - every object that gets a Course and a DomainContext receives that message, not just the VM that I've designated the Target.

So, second question: Is that by design, or is that a bug, or am I doing something wrong?

Thanks!

A: 

Messaging is more useful when you need to communicate from one ViewModel to another, or you need to send a message where zero to many things can take action on it. From your View's code behind, I think you should just call your ViewModel directly. Its easy enough - here's how I usually do it in my code.

public partial class ExampleView : UserControl
{
    private IExampleViewModel ViewModel
    {
        get { return this.DataContext as IExampleViewModel; }
    }

    public ExampleView()
    {
        InitializeComponent();

        // Call directly to my View Model
        ViewModel.SomeMethod();

        // Register for View Model's event
        ViewModel.SomeEvent += ViewModel_SomeEvent;
    }

    private void ViewModel_SomeEvent(object sender, EventArgs e)
    {
        // do stuff
    }
}

I also included in the example how I handle communications from the ViewModel back to the View - through events.

Matt Casto
Okay, so you make an Interface for your ViewModel to prevent coupling. I guess that would be useful for at least setting the Entity Objects, even everything else is different.
BoB
You don't have to use an interface, its just a good habit to get into. I admit it does add ceremony to the creation of a ViewModel, but I've found its worth the extra effort. Also, another thing I do that you don't have to do is I use a DI/IoC container in my ViewModelLocator. I use Ninject but you could also easily use Unity or Castle Windsor.
Matt Casto
A: 

To answer your second question, if you're sending a NotificationMessage of a specific type, anything registering for that same message type will receive the message. If you want to limit who receives the message, either create a new message class inheriting from MessageBase or NotificationMessage or whatever, send your message with a Token, or have an if statement in your message receive handler to filter out messages you don't care about.

Matt Casto
Yeah, I get all that. My point was really that there is a Message, it has a Target, that would seem to imply that the Target should be the one to receive the Message. As that seems simple to implement, I was wondering if it really doesn't exist, or if I wasn't setting the Target or Sending correctly.
BoB
Okay, I missed that you're setting a target for your NotificationMessage in your example. Try casting this.DataContext as your exact ViewModel type and see if that makes a difference? If not, try adding the MVVM Light Toolkit projects to your solution and step through and see why other ViewModels are getting the message too. Either you'll uncover a nasty bug, or you'll figure out whats wrong with your code. :-)
Matt Casto
That's another good idea, thanks!
BoB

related questions