Améliorez la lisibilité de votre code et simplifiez vous la vie avec NotifyPropertyWeaver

Quand vous réalisez votre ViewModel pour une application WPF, Windows Phone ou Silverlight, vous utilisez sans cesse OnPropertyChanged et avez à créer un code ressemblant très vite à ceci :

public class Person : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }

    private string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Alors que de base, vous pourriez très bien avoir ceci :

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }

}

Pourquoi s’embêter avec tout ça ? Personnellement, je trouve ça chiant, long, et ça réduit fortement la lisibilité de mon code en me retrouvant avec 52 lignes de code au lieu de 16.

En lisant un article de Scott Hanselman sur sa première expérience de développement sur Windows Phone 7, j’ai découvert NotifyPropertyWeaver. Un plugin pour Visual Studio que j’ai trouvé réellement pratique et que j’ai donc décidé de partager avec vous.

Mais que fait NotifyPropertyWeaver ?

NotifyPropertyWeaver ajoute automatiquement un tâche au MSBuild qui, juste après la compilation, va modifier votre code lui même afin d’ajouter tout ce qui est nécessaire à la notification de votre ViewModel. Tout ce qu’il vous reste à faire, c’est implémenter INotifyPropertyChanged.

Vous n’avez plus qu’à écrire le second code que je vous ai donné ci-dessus, et une fois compilé, il ressemblera au premier. Magique non ?

Installation

Commencez par installer NotifyPropertyWeaver en utilisant le Package Manager Console ou le Dialog de Nuget.

  • Via la Package Manager Console, utilisez la commande install-package notifyPropertyWeaver

Installation via la Package Manager Console

  • Via le manager de packages Nuget, recherchez simplement “NotifyPropertyWeaver” et cliquez sur installer.

Installation via le manager de packages Nuget

Utilisation

Écrivez le code de votre ViewModel simplement, en y insérant les propriétés sans chichis, juste ce dont vous avez besoin, comme le second exemple de code de cet article. N’oubliez pas d’implémenter INotifyPropertyChanged comme suis :

public class Person : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

Et voilà, c’est tout ce que vous avez à faire, rien de plus ! En espérant que cet outil vous aidera et qu’il sera, comme pour moi, ce genre de petit plus qu’on apprécie fortement en tant que développeur fainéant Sourire

  • http://www.renauddumont.be/ Renaud Dumont

    J’tâcherai d’y penser pour mes prochains petits projets ^^ Effectivement, c’est parfois long de placer toutes les notifications!

    Et puis deuxième avantage: c’est plus facile à maintenir! Parce qu’avec un OnPropertyChanged(string prop), si on renomme une propriété et qu’on ne fait pas gaffe, on casse un binding :(

    • http://www.kevinrapaille.com Kévin Rapaille

      Renaud, pour ce qui est de la maintenance de ton code si tu n’est pas fan de NotifyPropertyWeaver, il existe aussi la solution de la méthode d’extension dont on parle dans cette article (très bien fait et très instructif au passage) : http://blogs.developpeur.org/fredhamel/archive/2008/06/15/wpf-r-glons-son-compte-inotifypropertychanged-d-rivation-r-flexion-aop-entlib-string-net-extension.aspx

      C’est la méthode que j’utilisais avant de découvrir NotifyPropertyWeaver :)

      • http://www.renauddumont.be/ Renaud Dumont

        Ouais mais comment tu fais avec ton exemple du dessus? Dans le cas où tu fais un set sur le GivenNames, comment notifier le FullName?

        Sinon j’avais aussi vu une autre possibilité, avec des expressions lambda, mais ça utilisait aussi la réflection, et j’avais vu des tests de performance où la méthode des expressions lambda étaient au moins 10 fois plus lente ^^ peut-être même plus, j’me rappelle plus trop :) Enfin perso je ne l’ai pas encore utilisé, mais je le ferai surement sans scrupule prochainement! ^^

  • http://www.renauddumont.be/ Renaud Dumont

    Haa voilà, avec NotifyPropertyWeaver il y a toute une série d’attributs assez pratiques ^^ Pour l’example de l’article, on peut le faire de deux manières:

    La propriété AlsoNotifyFor de l’attribut NotifyProperty qui indique d’injecter une notification en plus pour les propriétés données:

    [NotifyProperty(AlsoNotifyFor = new[] { « FullName » })]
    public string GivenNames { get; set; }

    Ou bien, l’attribut DependsOn qui indique qu’une propriété doit être notifiée quand d’autres sont modifiées:
    [DependsOn("GivenNames","FamilyName")]
    public string FullName { get; set; }

    Et puis aussi, y’a un attribut DoNotNotify, pratique si tu exposes directement ton modèle et que tu ne veux pas notifier toutes les propriétés! :)

    Effectivement c’est vraiment cool :) J’pensais qu’on risquait de perdre un peu le contrôle sur les notifications, avec du code inutile par exemple ou de la flexibilité en moins, mais visiblement c’est pas le cas du tout! ^^

    • http://www.kevinrapaille.com Kévin Rapaille

      Effectivement ce n’est pas le cas du tout :) Il y a vraiment moyen d’optimiser le code généré par NotifyPropertyWeaver avec les attributs. Je n’ai pas encore eu l’occasion de tous les regarder mais j’en ai vu également 2-3 autres qui peuvent être utile dans des cas très spécifiques. J’essayerai d’un peu plus approfondir la chose avant d’en dédier un nouvel article !