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

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01

- SharePoint Online: Script PowerShell pour supprimer une colonne dans tous les sites d’une collection par Blog Technique de Romelard Fabrice le 11-27-2018, 18:01