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

Windows Presentation Foundation Discussion :

Collection, List, ObservableCollection etc. Lequel Choisir ?


Sujet :

Windows Presentation Foundation

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2009
    Messages : 29
    Points : 24
    Points
    24
    Par défaut Collection, List, ObservableCollection etc. Lequel Choisir ?
    Bonsoir,

    J'ai une question qui me tracasse.
    J'utilise EF4 dans une Dal (qui renvoi une liste d'objets movie), qui est utilisée dans des Controller et binder à un VirtualWrapel d'une ListBox.

    Quel est le type de Collection à utiliser car là je m'y perd un peu :

    List, Collection, ListCollectionView, ObservableCollection, Dictionnaire, ReadOnlyCollection....

    Merci pour vos conseils.

    Jeff

  2. #2
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Du côté de ta DAL tu devrais renvoyer des collections ayant un sens métier, et non pas technique comme l'ObservableCollection.
    Ensuite il faut veiller à utiliser des interfaces (IList<>, IEnumerable<>...) plutôt que des implémentations (List<>, ...).

    Du côté de ton interface graphique en revanche tu as besoin d'une plus grande richesse technique que tu obtiendras via l'ObservableCollection.

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    effectivement il ne devrais pas y avoir de lien direct entre la DAL et l'UI... c'est pas bien lol

    disons qu'en fait ta DAL c'est EF4 et notamment le ContextObject de EF4.
    ta BOL c'est tes entités de préférence POCO
    donc en fait il te faut une BLL entre ta DAL et ton viewmodel...

    ta BLL devrait retourner des IList<> ou des IEnumerable<> et ton ViewModel exposer des ObservableCollection<> pour ton UI...

    le ViewModel finalement c'est une quatrième couche, et l'ui une cinquième.
    parfois on regroupe un peu, la BLL et le ViewModel ensembles... c'est bien dans les petites projets avec une criticité faible sur les données manipulées
    mais quand on commence à causer gros projet, données critiques, et surtout où tu es susceptible de multiplier les tiers comme des ptits pains... vaut mieux bien séparer.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2009
    Messages : 29
    Points : 24
    Points
    24
    Par défaut
    Il y a bien une BL entre les deux je te rassure

    Donc en resumé:

    Dal : IList
    BL : IList
    UI : ObservableCollection

    J'ai bon ?

    ListCollectionView ca sert a quoi ? en en terme de performance qui est le plus légé ?

    Merci

  5. #5
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    ListCollectionView ca sert a quoi ?
    A définir et utiliser des vues générées par des opérations de tri, groupage, ...

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2009
    Messages : 29
    Points : 24
    Points
    24
    Par défaut
    Ça veut dire qu'on peut ensuite retrier la collection sans repasser par la db ?

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    ba en fait que tu manipule une IList ou ce que tu veux une fois que les objets ont quitté la DAL, ils sont en mémoire... toute interaction sur eux à moins de remonter à la DAL reste en mémoire et n'interfère pas avec la base de données.

    utiliser Linq sur des IEnumerable ou des IList, ou d'autres collections, se fait exclusivement côté programme, car on parle de Linq to Object et non Linq To SQL ou Entities.
    donc les vues permettent de trier ou filtrer allégrement coté programme sans du tout utiliser l'interaction avec la base de données.

    ListCollectionView, ou d'autres permettent par exemple de fournir un set d'objet complet, et par le biais des éléments de trier, trier la collection dans un sens ou dans l'autre, et filtrer les objets, ainsi la vue ne retourne que les objets correspondant au filtre, mais cependant modifier les filtres change également les objets visible de la vue, par visible j'entend accessible par l'énumérateur de celle ci.
    Une vue conserver la collection originale fournie et t'expose une collection interne, manipulée pour correspondre aux critères que tu lui impose, tris, filtres ...
    ca peut être pratique en amont d'une BL.
    et c'est très utilisé entre le viewmodel et l'ui... mais là tu n'a pas besoin de spécifier une vue directe...

    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
     
    public class ViewModel : ViewModelBase
    {
      public ObservableCollection<Person> Persons {get; private set;}
      private ICollectionView _personView;
     
      public ViewModel() {
        var ctx = new EntitiesContext();
        Persons = new ObservableCollection<Person>(ctx.Persons);
        _personView = CollectionViewSource.GetDefaultView(_Persons )
     
        if (_personView != null) _personView.CurrentChanged += OnPersonChanged;
      }
     
      ...
    }
    si tu est adepte du pattern mvvm tu as déjà avoir du voir ce genre de code, qui permet grace à la méthode OnPersonChanged de récupéré l'élément courant sélectionné dans la vue par défaut associée à ton observablecollection, qui est la collection sur laquelle est effectuée le bind dans l'ui.
    en réalité toute opération sur la vue _personView impacte sur ce qui est affiché par l'ui bindé sur l'observablecollection, mais si tu filtre sur _personView, l'ui n'affiche que les éléments qui respecte le filtre, mais les objets qui ne sont pas visibles ne sont pas pour autant déréférencés.

    Les ListCollectionView on un fonctionnement similaire est sont donc intéressante entre ta BLL et d'autres couches éventuelles avant le ViewModel.

  8. #8
    Membre habitué Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Points : 190
    Points
    190
    Par défaut
    Bonjour,

    Une ObservableCollection est, comme son nom l'indique, une collection que l'on peut "observer". Elle permet de notifier à des écouteurs l'ajout ou la suppression d'un élément (ceci est en fait du à l'implémentation de l'interface INotifyCollectionChanged). Mais cela doit rester ta collection "Source" i.e là ou tu stockes tes éléments (et juste stocker).

    Quant à la collection de présentation pour la vue, il est bien plus puissant d'utiliser une ListCollectionView qui, comme dit dans le post précédent, te permet d'afficher une vue de ta collection "Source", c'est-à-dire ordonnée et/ou filtrée comme tu le souhaites ainsi que l'élément courant, notion qui n'existe pas dans une ObservableCollection (et qui n'aurait rien à y faire).

    L'énorme avantage de ceci est que tu n'impactes pas ta collection "Source" lorsque tu effectues toutes ces opérations. On peut alors créer plusieurs vues d'une même source. Si celle-ci est la collection de nombres entiers inférieurs à 100 tu peux créer trois vues de cette même source : une triée par ordre croissant, une n'affichant que les nombres premiers, et une n'affichant que les entiers pairs affichés par ordre décroissant. De plus, si ta collection vient à changer, ce changement est automatiquement répercuté sur ses trois vues (et donc, prise en compte des filtres et tris). Faire la même chose sans une vue de collection serait extrêmement fastidieux...

    Lors du binding avec un ItemsControl n'oublie pas l'attribut IsSynchronizedWithCurrentItem pour que l'élément courant de ton ItemsControl corresponde à celui de la vue de ta collection "Source".

    Bon courage à toi

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    titourock ta déjà fait du MVVM ou pas ?

    ta déjà essayé d'utiliser OberverableCollection<T> avec le databinding...

    on dirais bien que non.
    L'exemple que je donne, même s'il est incomplet n'est pas dénué de sens...

    En réalité, dès lors que tu fourni une ObservableCollection<T> au Databinding de WPF, la vue (view) que tu récupère coté ModelView est la même que celle manipulée par le databinding...
    et oui la première chose qu'il fait c'est obtenir une vue par défaut sur l'ObservableCollection<T>. Donc quand tu demande cette vue par défaut, quand tu fait des modifs sur cette vue elles sont affichées, sans toucher à l'ObservableCollection<T>.
    de même si tu agit sur l'ObservableCollection<T>, via INotifyCollectionChanged, grace au databinding, tout change également.

    Quands les grands pontes comme John Smith exposent eux même une ObservableCollection plutot qu'une ListCollectionView, c'est qu'il y a une bonne raison...
    maintenant c'est sure si ta jamais observé toi même...

    Maintenant si tu ne fait pas de MVVM...

    l'ObservableCollection<T> est une collection avec des mécanismes totalement inintéressants à des passages entre une DAL et une BLL, et même au dessus, entre une BLL et la couche supérieure...

    Effectivement si tu dois avoir 3 vues différentes sur la même collection, il vaut mieux exposer un ListCollectionView particulier, sur les contrôles qui ne sont pas susceptibles d'altérer la collection source (ajouter/retirer des éléments automatiquement).

  10. #10
    Membre habitué Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Points : 190
    Points
    190
    Par défaut
    Citation Envoyé par cinemania Voir le message
    titourock ta déjà fait du MVVM ou pas ?

    ta déjà essayé d'utiliser OberverableCollection<T> avec le databinding...

    on dirais bien que non.

    maintenant c'est sure si ta jamais observé toi même...
    Oui je tente de faire du MVVM et je précise "tente" car je ne prétends pas maîtriser le sujet à fond. A la question "as-tu déjà essayé d'utiliser OberverableCollection<T> avec le databinding..." la réponse est oui mais mon explication portait sur le fait qu'il faut bien démarquer l'utilité d'une vue d'une collection de la collection "source".
    La question initiale en début de topic portait sur l'utilité de List, Collection, ListCollectionView, ObservableCollection, Dictionnaire, ReadOnlyCollection etc...je ne donnais que l'utilité de deux de ces collections.

    Enfin comme le précise Mitsu Furuta dans un de ces webcasts, lorsque l'on binde par exemple une listbox à une collection, une vue par défaut est crée mais je pense qu'il est mieux de la "créer" soi-même cette vue pour bien avoir conscience de son existence car l'on peut être tenté de modifier l'ObservableCollection pour retirer des éléments "physiquement" alors que la vue est faite pour cela via les filtres.

    Pour corroborer ceci, le tutoriel sur developpez : http://japf.developpez.com/tutoriels...-et-testables/

    et dont l'exemple que j'ai donné est reflété par ce bout de code :

    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
    public MasterViewModel(Database db)
            {
                this.db = db;
                this.persons = new ObservableCollection<PersonViewModel>();
     
     
     
                foreach (Person person in this.db.Persons)
                {
                    this.persons.Add(new PersonViewModel(person));
                }
     
                this.collectionView = CollectionViewSource.GetDefaultView(this.persons);
                if(this.collectionView == null)
                    throw new NullReferenceException("collectionView");
     
                this.collectionView.CurrentChanged += new EventHandler(this.OnCollectionViewCurrentChanged);
            }
    On crée une collection "Persons" et récupère la vue par défaut (qu'on aurait bien du créer si l'on avait eu à faire plusieurs vues de cette même collection et c'est là que ListCollectionView est utile car prendre la vue par défaut pour trois listbox ne fonctionnerait évidemment pas) sur laquelle on se binde :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <ListBox Grid.Row="1"
                     ItemsSource="{Binding Persons}"
                     IsSynchronizedWithCurrentItem="True"
                     SelectionMode="Multiple"/>
    et non sur la collection "source" qui est une ObservableCollection...
    Alors oui on peut se binder sur une ObservableCollection mais il est extrêmement important d'avoir en tête qu'il existe une surcouche à celle-ci : sa vue.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    En fait, binder sur une ObservableCollection ou une CollectionView, ça change pas grand chose... Comme ça a été mentionné plus haut, quand on binde sur une ObservableCollection, ça crée implicitement une CollectionView qu'on peut récupérer et manipuler avec CollectionViewSource.GetDefaultView. Il faut juste garder à l'esprit qu'une CollectionView n'est pas vraiment une collection, mais comme son nom l'indique c'est une vue sur la collection source.

    Maintenant, certains préfèrent binder sur une CollectionView, d'autres sur une ObservableCollection... C'est surtout une question de préférence et/ou de cas particulier d'utilisation. Bien sûr, si on veut avoir plusieurs vues sur la même collection source, on est obligé de manipuler explicitement des CollectionViews...

  12. #12
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    avec une DataGrid où tu autorise les Ajout/Suppression, il faut travailler directement avec l'ObservableCollection de façon à bien altérer l'ObservableCollection et non une vue, mais de toute façon les altérations sur la vue sont propagées.

    Effectivement le IsSynchronizedWithCurrentItem dans le ItemsControl est primordial si on souhaite savoir dans le ViewModel quel est l'élément courant sélectionné

    Bon moi je retourne implémenter un truc propre pour gérer la multi-sélection... parce que mettre une propriété IsSelected sur chaque item... c'est un peu moyen, dans le genre

  13. #13
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Citation Envoyé par cinemania Voir le message
    Bon moi je retourne implémenter un truc propre pour gérer la multi-sélection... parce que mettre une propriété IsSelected sur chaque item... c'est un peu moyen, dans le genre
    Pourquoi ?

  14. #14
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2009
    Messages : 29
    Points : 24
    Points
    24
    Par défaut
    Merci a tous pour vos réponses.

  15. #15
    Membre habitué Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Points : 190
    Points
    190
    Par défaut
    En ce qui concerne la multisélection (qui manque cruellement à l'heure actuelle à WPF), il y a ce lien fort intéressant : http://grokys.blogspot.com/2010/07/m...-part-iii.html

    J'avais déjà trouvé des exemples où l'on pouvait binder la sélection d'un itemscontrol mais cela restait très spécifique (bien que très intéressant en utilisant les propriétés attachées)...La chose importante était donc de créer une ListCollectionView ayant un "CurrentItems" (analogue de CurrentItem dans une ListViewCollection).

    C'est chose faite ici, et cela a l'air pas mal

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    voila titourock on se rejoint là...

    Davcha, c'est logique, devoir modifier tes objet métiers et y ajouter une propriété qui n'a finalement d'usage que de stocker l'état de sélection dans l'UI... c'est plus que moyen, et même en passant par un objet de mapping entre l'objet métier et l'objet UI... c'est plus que critiquable comme technique.
    et c'est trop loin du pattern utilisé pour l'élément courant.

    c'est bien pour un petit projet, où ta pas trop de couches dissociées, mais dès lors que tu multiplie les couches comme des ptits pains, ca commence vite à ne plus être envisageable.

  17. #17
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    En même temps, cinemania, dans pas mal de cas, tu ajoutes un intermédiaire (un viewmodel) entre ton objet métier et ton UI, pour y adjoindre des fonctionnalités techniques liées à l'UI.

  18. #18
    Membre habitué Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Points : 190
    Points
    190
    Par défaut
    Citation Envoyé par davcha Voir le message
    En même temps, cinemania, dans pas mal de cas, tu ajoutes un intermédiaire (un viewmodel) entre ton objet métier et ton UI, pour y adjoindre des fonctionnalités techniques liées à l'UI.
    Oui ce n'est pas faux mais alors on se retrouve avec deux façons de gérer les sélections courantes ICollectionView et "SelectedItems maison". Ou alors il faut décréter que tout doit être fait avec le "sélection maison". Je pense de toutes façons que tant que cela n'existera pas en natif (à quand sa prise en charge ?) cela restera tout de même bancal quelquesoit la solution choisie...

  19. #19
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Faut avouer, tout de même, que la propriété IsSelected sur le ViewModel est bien pratique.

    Comment fais-tu pour savoir si un objet est sélectionné, quand ton datacontext est cet objet lui-même (ou son viewmodel) ?

  20. #20
    Membre habitué Avatar de titourock
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 156
    Points : 190
    Points
    190
    Par défaut
    Citation Envoyé par davcha Voir le message
    Comment fais-tu pour savoir si un objet est sélectionné, quand ton datacontext est cet objet lui-même (ou son viewmodel) ?
    Pardon, je ne saisis pas bien ta question . Pourrais-tu en donner un exemple simple ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. C ou C++ ? Lequel choisir ?
    Par strategos dans le forum Langages de programmation
    Réponses: 404
    Dernier message: 09/12/2022, 21h08
  2. Réponses: 3
    Dernier message: 25/04/2007, 10h45
  3. Curseur et lock : Les différence & lequel choisir
    Par BilTCD dans le forum Access
    Réponses: 2
    Dernier message: 22/10/2004, 15h03
  4. [FEDORA] Lequel choisir entre Fedora i386 et x86 pour un xeon?
    Par Oberon dans le forum RedHat / CentOS / Fedora
    Réponses: 7
    Dernier message: 13/07/2004, 15h52
  5. [Conseil] Glut vs SDL, lequel choisir
    Par Mathieu.J dans le forum GLUT
    Réponses: 15
    Dernier message: 08/06/2004, 09h47

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