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

Silverlight Discussion :

datagrid, colonne de selection (avec option select all), le tout en MVVM


Sujet :

Silverlight

  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Points : 674
    Points
    674
    Par défaut datagrid, colonne de selection (avec option select all), le tout en MVVM
    Bonjour à tous,

    Je cherche une solution réutilisable pour implémenter une colonne de datagrid avec l'option select all. => un booléen à true ou false sur chaque row qui peuvent être "valuées" en une fois grâce au check all....
    J'ai quelque chose qui marche, mais j'aimerai que ce soit réutilisable, car j'ai le cas dans plusieurs datagrids (parfois dans le même écran, même view model).

    Pour l'instant, j'ai défini un custom "DataGridColumnHeaderStyle" avec le checkbox dedans, qui est bindé sur une propriété du viewmodel (qui elle passe en revue la liste des rows et change la valeur du check box de la cellule). Le problème c'est qu'en fonction du cas la propriété derrière n'a pas le même nom.
    Je ne veux pas avoir à redéfinir 10x le même DataGridColumnHeaderStyle mais avec simplement la ligne de binding à la propriété qui change...

    Faut-il que j'implémente ma propre version de DataGridColumn (abstract), y-a-t-il moyen d'utiliser les triggers ?? Autre ???

    Je suis preneur de toute idée...

    Merci,
    Christophe

  2. #2
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Bonjour Christophe,

    Je me suis penché sur ton problème. Voici un (bon) début de solution :

    Le xaml tout d'abord :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
            <sdk:DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
                <sdk:DataGrid.Columns>
                    <local:DataGridCheckBoxAllColumn Binding="{Binding IsCool}" BindingAll="{Binding AreCool, Mode=TwoWay}">
                    </local:DataGridCheckBoxAllColumn>
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>

    Code c# : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
        public class DataGridCheckBoxAllColumn : DataGridCheckBoxColumn
        {
            public Binding BindingAll
            {
                get;
                set;
            }
     
            public override Binding Binding
            {
                get
                {
                    return base.Binding;
                }
                set
                {
                    base.Binding = value;
                }
            }
     
            bool isLoaded = false;
     
            // on se sert de cette methode comme d'une methode Load :)
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                if (isLoaded == false)
                {
                    isLoaded = true;
     
                    string xaml = @"<ControlTemplate
                    xmlns=""http://schemas.microsoft.com/client/2007"">
                    <CheckBox ";
     
                    if( this.BindingAll != null )
                    {
                        xaml += @"IsChecked=""{Binding " + this.BindingAll.Path.Path + @",Mode=TwoWay}""";
                    }
     
                    xaml += @"/>";
                    xaml += @"</ControlTemplate>";
     
                    ControlTemplate template = (ControlTemplate)XamlReader.Load(
                               xaml
                             );
     
                    Style style = new Style(typeof(DataGridColumnHeader));
     
                    style.Setters.Add(new Setter(DataGridColumnHeader.TemplateProperty, template));
     
                    this.HeaderStyle = style;
                }
                return base.GenerateElement(cell, dataItem);
            }
        }

    Ici j'ai mis en place un Binding que j'appelle BindingAll qui pointe vers la valeur que la checkbox du header doit changer et ainsi toucher les valeurs des autres checkboxs contenus dans les lignes.

    Les classes representant les données dont la propriété AreCool de la classe Datas qui controlent les enfants

    Code c# : 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
        public class Datas : ObservableCollection<Data>
        {
            public bool AreCool
            {
                get
                {
                    foreach (Data data in this)
                    {
                        if (data.IsCool == false)
                            return false;
                    }
     
                    return true;
                }
     
                set
                {
                    foreach (Data data in this)
                    {
                        data.IsCool = value;
                    }
                }
            }
        }
     
        public class Data : INotifyPropertyChanged
        {
            public bool IsCool
            {
                get
                {
                    return this.isCool;
                }
     
                set
                {
                    if( this.isCool != value )
                    {
                        this.isCool = value;
                        this.RaisePropertyChanged("IsCool");
                    }
                }
     
            }
     
            private bool isCool = false;
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            protected void RaisePropertyChanged( string propertyName )
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

    On peut aller plus loin mais c'est un (bon) début !

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Points : 674
    Points
    674
    Par défaut
    Bonjour Samuel,

    L'idée me plaît !! Je vais m'y pencher.
    Par contre, la partie injection de code dans "GenerateElement" reste mystérieuse pour moi. Si j'ai bien compris, on injecte la checkbox d'entête, mais on en perd la blenadbilité, le styling, etc... N'est-il pas? (ce n'est pas un problème en soi, c'est juste pr bien comprendre)

    Merci !
    Christophe

  4. #4
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Par contre, la partie injection de code dans "GenerateElement" reste mystérieuse pour moi. Si j'ai bien compris, on injecte la checkbox d'entête, mais on en perd la blenadbilité, le styling, etc... N'est-il pas? (ce n'est pas un problème en soi, c'est juste pr bien comprendre)
    Oui c'est exactement cela. En fait tu crées un style à la volée qui contient le template de ton Header. Dans ce template tu peux intégrer la valeur de BindingAll mais on pourrait faire autrement je pense (sans doute plus Blendable!)

Discussions similaires

  1. Changer font-size sur un select avec options
    Par dark0502 dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 09/10/2013, 00h28
  2. Récupération d'un select avec option multiple
    Par Xenonmax dans le forum Langage
    Réponses: 3
    Dernier message: 23/03/2011, 14h14
  3. Réponses: 9
    Dernier message: 07/03/2011, 16h18
  4. [POO] Select avec option
    Par snaxisnake dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 15/09/2008, 17h16
  5. modifier option select avec tableau
    Par calitom dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 29/11/2006, 12h12

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