Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

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

Actualités

[WPF] Comment récupérer la valeur d'un attribut personnalisé lors du DataBinding ?

J'ai répondu récemment à une question, sur les forums de Developpez.com, qui était forte intéressante et qui valait bien un petit post sur mon blog.

Pour faire simple, le demandeur était dans le cas suivant:

  • Une listbox liée à une liste de personne
  • Un attribut personnalisé sur les propriétés de la classe Person

Son besoin était simple: il voulait pouvoir afficher, lors d'un binding, la valeur d'une des propriétés de l'attribut personnalisé. En terme de code, nous avions donc ceci:

public class Person

{

    [PersonProperties("LastName : ")]

    public string LastName { get; set; }

 

    [PersonProperties("FirstName : ")]

    public string FirstName { get; set; }

}

 

public class PersonCollection : ObservableCollection<Person>

{

}

 

[global::System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]

sealed class PersonPropertiesAttribute : Attribute

{

    public string Header { get; private set; }

 

    public PersonPropertiesAttribute(string header)

    {

        this.Header = header;

    }

}

Il faut à présent remplir notre collection de personne, par exemple lors du chargement de la fenêtre:

private void Window_Loaded(object sender, RoutedEventArgs e)

{

    ObjectDataProvider odp = this.TryFindResource("PersonCollectionDS") as ObjectDataProvider;

 

    if (odp != null)

    {

        PersonCollection pc = odp.Data as PersonCollection;

 

        if (pc != null)

        {

            pc.Add(new Person() { LastName = "LEBRUN", FirstName = "Thomas" });

            pc.Add(new Person() { LastName = "SANTIN", FirstName = "Florent" });

            pc.Add(new Person() { LastName = "SENTENAC", FirstName = "Philippe" });

            pc.Add(new Person() { LastName = "FURUTA", FirstName = "Mitsuru" });

        }

    }

}

Maintenant, il faut faire en sorte que, lors du binding, on arrive à accéder à l'attribut "PersonProperties" (et à sa valeur) et à l'afficher. Pour cela, il faut déjà mettre en place le binding, en utilisant un convertisseur auquel on va passer un paramètre:

<TextBlock HorizontalAlignment="Right" Margin="0,17,8,0" VerticalAlignment="Top" Width="126" Height="16" Text="{Binding Path=SelectedItem, Converter={StaticResource GetPersonAttributeConverter}, ConverterParameter=LastName, ElementName=lbPersons, Mode=Default}" TextWrapping="Wrap" x:Name="tbLastName"/>

<TextBlock HorizontalAlignment="Right" Margin="0,52,8,0" VerticalAlignment="Top" Width="126" Height="16" Text="{Binding Path=SelectedItem, Converter={StaticResource GetPersonAttributeConverter}, ConverterParameter=FirstName, ElementName=lbPersons, Mode=Default}" TextWrapping="Wrap" x:Name="tbFirstName"/>

Comme vous pouvez en douter, toute la magie va se passer dans le convertisseur, qui va tout simplement faire un peu de reflection sur l'objet passé en paramètre (un objet de type Person) et accéder aux attributs personnalisés:

public class GetPersonAttributeConverter : IValueConverter

{

    #region IValueConverter Members

 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        string result = string.Empty;

 

        if (value != null)

        {

            Person p = value as Person;

 

            if (p != null)

            {

                var properties = p.GetType().GetProperties();

 

                foreach (var propertyInfo in properties)

                {

                    var attributes = propertyInfo.GetCustomAttributes(typeof(PersonPropertiesAttribute), true);

 

                    if (((PersonPropertiesAttribute)attributes.GetValue(0)) != null)

                    {

                        string header = ((PersonPropertiesAttribute)attributes.GetValue(0)).Header;

 

                        string parameterToUse = parameter as string;

 

                        if (parameterToUse != null)

                        {

                            if (header.Contains(parameterToUse))

                            {

                                switch (parameterToUse)

                                {

                                    case "LastName":

                                        result = string.Concat(header, p.LastName);

                                    break;

 

                                    case "FirstName":

                                        result = string.Concat(header, p.FirstName);

                                        break;

 

                                    default:

                                        break;

                                }

                            }

                        }

                    }

                }

            }

        }

 

        return result;

    }

 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    {

        return null;

    }

 

    #endregion

}

A l'exécution, le biding est bien mis en place et grâce à la reflection, nous accédons à la valeur des propriétés de notre attribut personnalisé:

image

Pour ceux qui veulent tester, vous trouverez le code source de la démonstration ici: Source

 

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: mardi 29 avril 2008 10:50 par Thomas LEBRUN
Classé sous : , ,

Commentaires

Frédéric Hamel a dit :

Hello Thomas, merci pour ce post c'est tres intéressant.

Le code du converter pourrait être simplifié :

if (value == null || parameter == null)

  return string.Empty;

var property =

value.GetType().GetProperty(parameter.ToString());

var attribute =

property.GetCustomAttributes(

typeof(PersonPropertiesAttribute), false)[0] as PersonPropertiesAttribute;

return string.Concat(

attribute.Header,property.GetValue(value, null));

voila j'espère que ça aidera :)

# avril 29, 2008 15:56

Thomas LEBRUN a dit :

Merci :)

# avril 29, 2008 18:28
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 12 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 15 heures et 32 minutes

- Faire de l'AJAX sans restrictions de domaine par Kévin Gosse le il y a 18 heures et 0 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