tags:

views:

34

answers:

1

I am trying to get a sample to work using MVVM Light and the Messaging Class. In the sample, I have a test project created from the MVVM Template for Silveright 4. I have added a button on the main page. When the button is clicked, it updates a property on the ViewModel. When the property is updated, I want to show a messagebox with the new value.

The key line of code is:

Messenger.Default.Register(this, new Action(ShowMessage));

I can get this to work in WPF, but not silverlight. It should call ShowMessage with the string parameter when the property changes, but it does not. If I use:

Messenger.Default.Send("Hello MVVM");

This works and the string is sent as a message to ShowMessage.

However, the message does not get sent if the property changes, even though the property was created with the MVVMINPC snippet and has the following line:

RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);

This should have the same effect as Messager.Default.Send but it seems to be ignored. ThePropertyChangedEvent is indeed raised, but the messanger part seems to be disconnected.

Am I doing something wrong? Here is the full MainViewModel:

public class MainViewModel : ViewModelBase
{
    public RelayCommand MyRelayCommand { get; set; }
    public const string MyPropertyPropertyName = "MyProperty";
    private string _myProperty = "test";

    public string MyProperty
    {
        get
        {
            return _myProperty;
        }

        set
        {
            if (_myProperty == value)
            {
                return;
            }

            var oldValue = _myProperty;
            _myProperty = value;
            RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
        }
    }

    public void DoSomething()
    {
        //Messenger.Default.Send("Hello MVVM"); //Works
        this.MyProperty = "Hello World"; //Doesn't work.
    }



    public void ShowMessage(string message)
    {
        MessageBox.Show(message);
    }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {

        Messenger.Default.Register(this, new Action<string>(ShowMessage));

        MyRelayCommand = new RelayCommand(new Action(DoSomething));

        this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MainViewModel_PropertyChanged);

    }

    void MainViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        MessageBox.Show(e.PropertyName);
    }


}public class MainViewModel : ViewModelBase
{
    public RelayCommand MyRelayCommand { get; set; }
    public const string MyPropertyPropertyName = "MyProperty";
    private string _myProperty = "test";

    public string MyProperty
    {
        get
        {
            return _myProperty;
        }

        set
        {
            if (_myProperty == value)
            {
                return;
            }

            var oldValue = _myProperty;
            _myProperty = value;
            RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
        }
    }

    public void DoSomething()
    {
        //Messenger.Default.Send("Hello MVVM"); //Works
        this.MyProperty = "Hello World"; //Doesn't work.
    }



    public void ShowMessage(string message)
    {
        MessageBox.Show(message);
    }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {

        Messenger.Default.Register(this, new Action<string>(ShowMessage));

        MyRelayCommand = new RelayCommand(new Action(DoSomething));

        this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MainViewModel_PropertyChanged);

    }

    void MainViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        MessageBox.Show(e.PropertyName);
    }


}v
A: 

OK, I found that the Register line should look like this:

Messenger.Default.Register(this, new Action<PropertyChangedMessage<string>>(ShowMessage));

The point being there are different types of messages, and you have to register the PropertyChangedMessage type to recieve property changed messages.

Then also, the Action that recieves the message needs to take the correct parameter, like this:

public void ShowMessage(PropertyChangedMessage<string> e)
    {
        MessageBox.Show(e.NewValue.ToString());
    }
Greg Hollywood
Your ShowMessage method can take PropertyChangedMessageBase instead of the generic PropertyChangedMessage<T> parameter. Also, you can use an overload of the messenger's Register method to register for all messages deriving from PropertyChangedMessageBase if you like.Messenger.Default.Register<PropertyChangedMessageBase>(this, true, ShowMessage);
Matt Casto
OK, thanks Matt.
Greg Hollywood