Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

Tout sur WPF, LINQ, C# et .NET en général !

Actualités

[WPF] Comment et pourquoi créer sa propre "MarkupExtension" ?

Lorsque l'on manipule du XAML, il n'est pas rare de rencontrer des choses comme ceci:

{Binding ...}, {StaticResource ...}, and {RelativeSource ...}

Ces chaînes de caractères, encadrées des signes {}, forment ce que l'on appelle des MarkupExtensions.

Il peut arriver, lors de vos développements WPF, que les fonctionnalités offertes par le XAML ne soient pas suffisantes. Pour pallier à ce problème, la solution est d'écrire la fonctionnalité manquante dans le ode behind. Cela marche très bien mais comment faire si l'on ne veut pas écrire cette fonctionnalité dans le code mais faire le maximum de choses en XAML ? On écrit sa propre MarkupExtension ! Smile

Pour faire cela, il n'y a rien d'extraordainire: il vous suffit de créer une classe qui hérite de MarkupExtension et de surcharger la méthode ProvideValue:

public override object ProvideValue(IServiceProvider serviceProvider)

{

    return "Hello World";

}

Notez que les conventions WPF veulent que le nom de votre extension doit-être XXXExtension mais, dans le code, vous pouvez utitliser simplement XXX: c'est la même chose pour les attributs .NET par exemple (qui se nomme YYYAttribute mais que l'on utilise sous la forme YYY):

<TextBlock Text="{CustomExtension:CalculateSum}" HorizontalAlignment="Center" VerticalAlignment="Center" />

Si vous souhaitez utiliser des paramètres, rien de bien compliquer: il vous suffit de déclarer des propriétés dans votre classe:

public double FirstNumber { get; set; }

public double SecondNumber { get; set; }

 

public override object ProvideValue(IServiceProvider serviceProvider)

{

    if (FirstNumber == 0.0 && SecondNumber == 0.0)

    {

        return "No parameters specify";

    }

    else

    {

        return Convert.ToString(FirstNumber + SecondNumber);

    }

}

Et ensuite, de les utiliser dans votre code XAML:

<TextBlock Text="{CustomExtension:CalculateSum FirstNumber=5, SecondNumber=20}" HorizontalAlignment="Center" 

VerticalAlignment="Center" />

A l'exécution, vous remarquez que l'affichage affiche bien le résultat escompté:

 image

Vous avez sans doute remarquez que la méthode ProvideValue renvoit un object: cela sous-entend que vous pouvez lui faire renvoyer ce que vous voulez (chaîne de caractères, images, entier, etc...). Cependant, dans la majorité des cas, vous connaissez le type que vous souhaitez renvoyer: c'est pourquoi il est bon de le spécifier, sur la classe, l'attribut MarkupExtensionReturnType (qui prend en paramètre le type à renvoyer) qui est utilisé par le parseur XAML à la compilation pour s'assurer que vous assigner un type correct à la propriété sur laquelle l'extension est utilisée:

[MarkupExtensionReturnType(typeof(string))]

Au final, votre classe (le code de votre extension) ressemblera donc à ceci:

[MarkupExtensionReturnType(typeof(string))]

public class CalculateSumExtension : MarkupExtension

{

    public double FirstNumber { get; set; }

    public double SecondNumber { get; set; }

 

    public override object ProvideValue(IServiceProvider serviceProvider)

    {           

        if (FirstNumber == 0.0 && SecondNumber == 0.0)

        {

            return "No parameters specify";

        }

        else

        {

            return Convert.ToString(FirstNumber + SecondNumber);

        }

    }

}

Bon développement à tous !

 

A+

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mercredi 14 mai 2008 10:52 par Thomas LEBRUN
Classé sous : ,

Commentaires

PlaTyPuS a dit :

Intéressant! Je savais pas qu'on pouvait faire ca ;-). Merci.

Par contre, crois-tu que c'est + performant que d'utiliser un converter? (dans un cas comme celui que tu démontres...)

thx, ++

# mai 16, 2008 10:40

Thomas LEBRUN a dit :

Je n'ai pas testé les performances mais dans un cas comme celui-ci, il aurait été difficile d'implémenter un converter.

C'est surtout pour des besoins différents....

# mai 16, 2008 10:45
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [WPF] Comment déclencher un évènement sur un contrôle ? par Thomas Lebrun le il y a 1 heure et 25 minutes

- [Expression Web] Astuce de la Semaine : Utilisation et Configuration des Extraits de Code par Chronos, Blog d'un Intégrateur .NET le il y a 16 heures et 44 minutes

- Faire de l'AJAX sans restrictions de domaine par Kévin Gosse le il y a 19 heures et 13 minutes

- [IronPython] : IronPython & Silverlight 2 - Part II par Kim's Blog le 07-22-2008, 14:50

- [WPF] Des requêtes NDepend pour analyser vos projets WPF par Thomas Lebrun le 07-21-2008, 09:27

- Liste de jeux pour Silverlight par Pierrick's Blog le 07-20-2008, 14:37

- T_PAAMAYIM_NEKUDOTAYIM par MadMatt le 07-19-2008, 16:16

- Et je mets le son.... par Pierrick's Blog le 07-19-2008, 12:09

- SharePoint : Comment interdire l’accès à un utilisateur pour tous les sites d’une Web Application par Blog Technique de Romelard Fabrice le 07-18-2008, 19:05

- VPC - Reset de la position de la console par Blog technique de Nicolas Boonaert le 07-18-2008, 16:29