IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[databinding] formatter/parser les propriétés d'objets bindés.


Sujet :

C#

  1. #1
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut [databinding] formatter/parser les propriétés d'objets bindés.
    Bonjour,

    J'aimerais savoir si il y a un moyen de formatter/parser les valeurs d'une colonne d'une DataGridView bindée à une datasource.
    Par exemple, la DataGridView est bindée à une liste de produits. Un objet produit possède une propriété prix qui est de type float. Dans la colonne prix de la DataGridView on souhaite afficher le prix suivit de la devise. Je sais que cela est possible à faire avec une textbox par exemple. Il suffit d'écrire cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
                ...
                Binding b = new Binding("Text", order, "Price");
                b.Format += new ConvertEventHandler(b_Format);
                b.Parse += new ConvertEventHandler(b_Parse);
     
                textBox1.DataBindings.Add(b);
            }
     
            void b_Parse(object sender, ConvertEventArgs e)
            {
                e.Value = decimal.Parse((string) e.Value, NumberStyles.Currency);
            }
     
            void b_Format(object sender, ConvertEventArgs e)
            {
                e.Value = ((decimal) e.Value).ToString("C");
            }
    Mais est ce possible quand les sources sont des collections comme dans le cas d'une DataGridView ?

    D'autre part j'ai une propriété de type Quantity dans ma classe Product et je souhaiterais afficher dans une des colonnes de ma DataGridView, non pas la valeur de sa méthode ToString() mais l'une de ces propriétés, en l'occurrence sa propriété Value de type float. Est ce possible ?

    Pour l'instant j'ai réussi à résoudre ces 2 problèmes en écrivant ma CustomSourceView (classe implémentant ITypedList) et en récrivant les propertyDescriptor dans la méthode GetItemProperties(). Mais j'aurais aimé savoir si il y une méthode plus simple/traditionnelle de procéder pour ces 2 cas de figures. Y t-il des pros du databinding dans le coin ?

    Merci d'avance pour vos suggestions.


    mathmax
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  2. #2
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    personne n'a jamais été confronté à ce genre de problème ?
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  3. #3
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par maa Voir le message
    J'aimerais savoir si il y a un moyen de formatter/parser les valeurs d'une colonne d'une DataGridView bindée à une datasource.
    Par exemple, la DataGridView est bindée à une liste de produits. Un objet produit possède une propriété prix qui est de type float. Dans la colonne prix de la DataGridView on souhaite afficher le prix suivit de la devise.
    Bien plus simple : il suffit de modifier la propriété format ("C", en l'occurence) de la DataGridViewCellStyle de la DataGridViewColumn en question.

    Citation Envoyé par maa Voir le message
    D'autre part j'ai une propriété de type Quantity dans ma classe Product et je souhaiterais afficher dans une des colonnes de ma DataGridView, non pas la valeur de sa méthode ToString() mais l'une de ces propriétés, en l'occurrence sa propriété Value de type float. Est ce possible ?
    Oui, c'est possible, si tu fais hériter Quantity de IFormattable. Ca te fait implémenter une fonction ToString enrichie ; il ne te reste qu'à créer un formattage perso, et à changer le format de la DataGridViewCellStyle de ta colonne.
    ಠ_ಠ

  4. #4
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Pas mal. Merci beaucoup.

    Je vois toutefois les limite suivantes:

    - Cette démarche à un sens tans que la méthode ToString() de IFormatable reflète ce qu'est vraiment l'objet. Mais si l'on souhaite afficher une propriété ou encore une sous-propriété ou même une expression basée sur des propriétés de cet objet, c'est un peu dômmage de faire autant de formatage que de cas d'utilisation pour le binding. Ce que je veux dire, c'est qu'un formatage pouvant être utilisé plusieurs fois à sa raison d'être, en revanche il serait dômmage d'encombrer la classe d'autant de formatages dont on a besoins différents binding... Tu ne penses pas ?

    - Si maintenant la classe dont je souhaite binder l'instance possède une propriété qui est une collection d'objet et que je souhaite afficher un de ces objets (ou une des propriétés de d'un de cas objets si l'on veut compliquer encore un peu les choses... ) dans une colonne de ma datagridview ? Que ferais-tu ?
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  5. #5
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Problématique intéressante Le truc, c'est que bien qu'elles soient des fonctions de "présentation", ToString et ses variantes sont des fonctions tellement générales (ToString est une méthode de object !) qu'elles sont implémentées par beaucoup de type de base. Vis à vis de la séparation en couches, est-ce logique que Int32 soit formattable ? Chépas, en tous cas il l'est ; c'est pour ça que je t'ai proposé d'implémenter IFormattable dans tes objets Après, libre à toi de faire la syntaxe que tu veux.
    Exemple : un client a un nom et un prénom. Tu peux faire un truc du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public string ToString(string format, IFormatProvider formatProvider)
    {
      switch ((format ?? string.Empty).ToUpper())
      {
        case "NOM": return _nom;
        case "PRENOM": return _prenom;
        case "NOMCOMPLET" : return _prenom + " " + _nom;
        default: return base.ToString();
      }
    }
    Mais un truc qui serait pas mal, c'est le modèle employé par l'attribut DebuggerDisplay. List<T> a cet attribut, sous cette forme :
    [DebuggerDisplay("Count = {Count}")]
    Surpuissant ! Ca permet de faire un ToString en spécifiant les propriétés de l'objet à afficher dans la chaîne de format.
    Ca demande un peu de Reflexion, mais ça peut être sympa à implémenter (si ça l'est pas déjà quelque part). Et là, si t'avais une grille de List<Société> dont une des colonnes est liée à la propriété "PDG" de l'objet Société, tu pourrais donner comme style à la colonne "{Nom} {Prenom}".
    ಠ_ಠ

  6. #6
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Oui mais ça serait pas typé... Si on veux afficher le résultat d'une expression contenant des propriétés l'objet, on appréciera que ces propriétés soient fortement typées...

    Mais que proposerais-tu si par exemple on souhaite afficher dans une des colonnes le nom de la société de notre List<Société> qui a le plus gros capital ?

    Je suis en train de travailler sur une "BindingSource" qui vient se greffer entre l'objet à binder et la datasource et qui implémenterai tout ça... mais si ça existe déjà en natif...

    Tu as l'air de te débrouiller en binding, si d'ailleurs tu veux jeter un coup d'œil à un problème que j'ai avec cette "BindingSource", n'hésite pas.
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

  7. #7
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par maa Voir le message
    Mais que proposerais-tu si par exemple on souhaite afficher dans une des colonnes le nom de la société de notre List<Société> qui a le plus gros capital ?
    Euh, si la source est une List<Société>, chaque ligne est bindée à une "Société", qui n'a qu'un seul capital

    Mais si une société a une liste de salariés et que tu veux afficher le plus haut salaire (c'est à dire au cas ou ton objet "Société" a une propriété qui est de type Liste), il n'y a pas en effet de moyen "trivial" d'afficher cette donnée par un simple formatage. En même temps, le système préconisé par Microsoft (à base de Ado.Net, DataTable & co) ne le permet pas non plus, il me semble.
    Mais le formatage reste un moyen puissant : il permet de "commander" une classe pour qu'elle fournisse une string. Ca permet donc de centraliser à un seul endroit cette transformation, qui est la fonction ToString. Comme je disais tout à l'heure, je sais pas si c'est très pertinent dans une optique de séparation en couches, mais ça a le mérite d'être lisible.

    Citation Envoyé par maa Voir le message
    Je suis en train de travailler sur une "BindingSource" qui vient se greffer entre l'objet à binder et la datasource et qui implémenterai tout ça... mais si ça existe déjà en natif...
    Je crois pas que ça existe, et le besoin s'en fait effectivement sentir
    ಠ_ಠ

  8. #8
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Euh, si la source est une List<Société>, chaque ligne est bindée à une "Société", qui n'a qu'un seul capital
    oui je pensais que cette listes de société était une propriété de la classe qu'on binde... on retombe sur ton exemple de list de salarié en fait.

    En même temps, le système préconisé par Microsoft (à base de Ado.Net, DataTable & co) ne le permet pas non plus, il me semble.
    Pour ma part je ne travaille pas avec avec les dataset et dataview mais directement avec des objets et du mapping OR. Je trouve cela plus propre.

    Mais le formatage reste un moyen puissant : il permet de "commander" une classe pour qu'elle fournisse une string. Ca permet donc de centraliser à un seul endroit cette transformation, qui est la fonction ToString.
    Oui c'est clair. Par exemple pour le cas de la quantité, ça me parait très justifié. On pourrait imaginer un formatage par unité de poids... (une quantité étant une valeur dans une certaine unité de poids). Il est tout à fait logique de mettre ce type de formatage quand celui-ci correspond à une caractéristique de l'objet.
    Par contre pour le cas d'afficher le salarié qui a le plus haut salaire, il semble bien qu'il faille utiliser une autre méthode, car si l'on commence à faire autant de formatage dans la classe qu'on a de besoin d'affichage, la classe risque vite d'être encombrée. Imaginons par exemple qu'on veuille dans une autre DataGridView afficher le salarié masculin âgé de plus de 40 ans ayant le salaire le plus bas...
    Voilà à quoi j'ai pensé : ma bindingSource intermédiaire réécrit tout les PropertyDescriptor de l'objet d'origine. En plus de cela, ma dbindingSource contient une collection de "fausses propriété". On les ajoutes de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    source.FakeProperties.Add("SalaireMax",
        //méthode get
        company =>
        {
            return (from salarie in company.Salaries 
                             orderby salarie.Salaire.descending
                             select salarie.Salaire).First().ToString(Devise);
        },
     
        //méthode set
        (company, value) =>
        {
            (from salarie in company.Salaries 
                             orderby salarie.Salaire.descending
                             select salarie.Salaire).First().Value = value;
        },
    );
    Avec un peu de linq dedans, c'est assez joli je trouve. De cette manière on peut afficher et modifier ) peu près ce que l'on veut dans notre datagridview et sans modifier la classe pour les besoins du moments.

    Bon c'est pas encore parfait. Il faut que j'optimise la méthode set pour qu'elle se serve du get... que je gère la mise à jour de la liste de salariés pour pas qu'on update un nouveau qui aurait un salaire plus élevé...

    Je serais très heureux de partager ma source, si ça intéresse quelqu'un, pour qu'elle soit critiquée et améliorées.
    ****************************************

    - I don’t write plumbing code anymore
    - I use PostSharp
    - And you?


    ****************************************

Discussions similaires

  1. Réponses: 3
    Dernier message: 28/01/2009, 11h57
  2. [CR ?] gerer les propriétés des objets via les formules?
    Par Flamby38 dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 25/06/2008, 17h01
  3. [Zope] Changer les propriétés d'un objet
    Par senacle dans le forum Zope
    Réponses: 1
    Dernier message: 27/09/2006, 11h32
  4. [Débutant] Initialiser les propriétés de tous les objets d'une ArrayList
    Par Tententai dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 23/05/2006, 20h24
  5. Réponses: 1
    Dernier message: 20/02/2006, 10h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo