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

- TechDays Paris 2012 : Session pleinière jour 3 par Blog Technique de Romelard Fabrice le il y a 19 heures et 54 minutes

- Mishra Reader : un lecteur RSS très Zune Style en Open Source ! par Cyril Sansus le il y a 22 heures et 28 minutes

- [framework 4] Les Tasks et le Thread UI par Fathi Bellahcene le 02-09-2012, 00:33

- Workflow Foundation 3 a un pied dans la tombe par Blog de Jérémy Jeanson le 02-08-2012, 22:15

- TechDays Paris 2012 : Nouvelles tendances du poste de travail - Bring Your own PC par Blog Technique de Romelard Fabrice le 02-08-2012, 19:42

- TechDays Paris 2012 : System Center Service Manager 2012 Vue d’ensemble par Blog Technique de Romelard Fabrice le 02-08-2012, 17:32

- TechDays Paris 2012 : Pleinière second jour par Blog Technique de Romelard Fabrice le 02-08-2012, 16:23

- TechDays Paris 2012 : Retour d'expérience sur la mise en place d'un Cloud Privé par Blog Technique de Romelard Fabrice le 02-08-2012, 16:04

- TechDays Paris 2012 : Comment SharePoint a sauvé mes TechDays par Blog Technique de Romelard Fabrice le 02-07-2012, 23:59

- Perspective 3.0 pour Silverlight 5.0 par Perspective le 02-07-2012, 22:39