Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Notifying that all properties have changed on a ViewModel

Tags:

mvvm-light

I am working on a Silverlight application using V3 SP1 of MVVM Light Toolkit.

My application is fully French/English. All UI elements (buttons, labels, etc.) and all the data (models). I need dynamic language switching and this is fully implemented and works with anything coming from a resource file. What I am struggling with is the ViewModels.

The Models have language specific prperties (DescriptionEn, DescriptionFr) and an additional property call LocalizedDescription which uses the current culture to return call the language specific property.

When the language changes (via a button click) I raise and broadcast (via the Messenger) a property changed event.

In each of my ViewModels, I register to receive the property changed message for the language swap.

I want to notify all the properties of the ViewModel that something has changed.

From: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx

The PropertyChanged event can indicate all properties on the object have changed by using either null or String.Empty as the property name in the PropertyChangedEventArgs.

However, since the toolkit abstracts the raising of the changed event with RaisePropertyChanged(...) I cannot get this to work. I have also examined the source of the tookit and discovered that RaisePropertyChanged calls VerifyPropertyName(..) which in turn returns an error is the property does not belong to the ViewModel. I also noticed that the VerifyPropertyName method is attributed with Conditional("DEBUG"), but even if I choose the Release configuration, the ArgumentException("Property not found") is still raised.

Does anyone know of a way to get this to work using the toolkit aside from manually calling RaisePropertyChanged for every property of the ViewModel?

Follow-up:

Based on the comment from Simon, I attempted to create my own class that extends ViewModelBase. I looked at the source on CodePlex and decided to create a single method called RaiseAllPropertyChanged(). It would simply be a copy of the RaisePropertyChanged(string propertyName) but without the parameter and without the call to VerifyPropertyName(...). I cannot get it to work. Here is what I have.

public class ViewModelBaseExtended : ViewModelBase
{
    protected void RaiseAllPropertyChanged()
    {
        var handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(String.Empty));
        }
    }
}

But I get a compiler error: The event 'GalaSoft.MvvmLight.ViewModelBase.PropertyChanged' can only appear on the left hand side of += or -=. This is a copy of the code that is used in the ViewModelBase.

Can someone offer some advice as to how to get this to work?

Solution:

I copied all the code from ViewModelBase into a new class. I then added the method RaisePropertyChanged() mentioned above which instantiates the PropertyChangedEventArgs class with String.Empty. This is now the new subclass for my ViewModels.

Thanks again to Simon for leading the way!

like image 772
Vincenzo Piscitelli Avatar asked May 20 '11 15:05

Vincenzo Piscitelli


3 Answers

In case you're reading this in 2016, you can use ObservableObject and notify that all of the properties have changed by doing:

RaisePropertyChanged(string.Empty);
like image 99
Tyrrrz Avatar answered Nov 25 '22 13:11

Tyrrrz


Unfortunately this is not possible with the current code-base of MVVMLight

In the short term your have 2 options:

  1. User your own custom base class. And by custom base class I mean "Do not inherit from the MVVMLight class".

  2. Download and compile MVVMLight in Release mode. This will force the "VerifyPropertyName" method to be excluded. Of course then you don't get the value of property name checks.

I am sure Laurent Bugnion will have this fixed soon.

like image 45
Simon Avatar answered Nov 25 '22 13:11

Simon


A lighter solution to this problem would have been to override RaisePropertyChanged(string propertyName) in your class :

protected override void RaisePropertyChanged(string propertyName)
    {
        if (propertyName != null)
        {
            base.RaisePropertyChanged(propertyName);
        }
        else
        {
            var handler = PropertyChangedHandler;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(null));
            }

        }
    }
like image 42
pleasereset Avatar answered Nov 25 '22 13:11

pleasereset