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 :

Bind les "SelectedItems" d'un Listbox


Sujet :

Windows Presentation Foundation

  1. #1
    Membre du Club
    Bind les "SelectedItems" d'un Listbox
    Bonjour, et d'avance merci du temps que vous voudrez bien me consacrer!

    J'ai un listbox_2 qui contient une liste de fruits et légumes

    J'ai un autre listbox_1 qui peut contenir un groupe de fruits et légumes (sous forme de texte...c'est peut-être une première erreur? Peut-être faudrait-il que ce soit des objets fruits_légumes?) et une recette

    Je voudrais qu'a chaque sélection d'un groupe (dans listbox_1) , l'on voit les fruits et légumes correspondants sélectionnés (dans listbox_2)
    ...et que cette sélection puisse être modifiée et mémorisée



    Malheureusement, tout cela reste très obscure pour moi...pourriez-vous m'aider à y voir plus clair!?

    Voici le code jusqu'à présent:

    C#
    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
    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
    59
    60
    61
    62
    public partial class MainWindow : Window
        {
            ItemList il;
            GroupList gl;
     
            public MainWindow()
            {
                InitializeComponent();
            }
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                il = new ItemList();
                ICollectionView cvs = CollectionViewSource.GetDefaultView(il);
                cvs.SortDescriptions.Add(new SortDescription("_type", ListSortDirection.Ascending));
                cvs.SortDescriptions.Add(new SortDescription("_name", ListSortDirection.Ascending));
                cvs.GroupDescriptions.Add(new PropertyGroupDescription("_type"));
                ListBox2.ItemsSource = cvs;
     
                gl = new GroupList();
                ICollectionView cvt = CollectionViewSource.GetDefaultView(gl);
                ListBox1.ItemsSource = cvt;
            } 
        }
     
        public class Item
        {
            public string _type { get; set; }
            public string _name { get; set; }
            public Item()
            {
            }
        }
        public class ItemList : ObservableCollection<Item> {
            public ItemList() {
                base.Add(new Item() { _type = "fruit", _name = "apple" });
                base.Add(new Item() { _type = "vegetable", _name = "potato" });
                base.Add(new Item() { _type = "fruit", _name = "banana" });
                base.Add(new Item() { _type = "vegetable", _name = "tomato" });
                base.Add(new Item() { _type = "fruit", _name = "pear" });
                base.Add(new Item() { _type = "vegetable", _name = "salad" });
                base.Add(new Item() { _type = "fruit", _name = "orange" });
                base.Add(new Item() { _type = "vegetable", _name = "onion" }); 
            }
        }
     
        public class Group
        {
            public string _groupname { get; set; }
            public List<String> _members { get; set; }
            public string _recipe { get; set; }
            public Group()
            {
            }
        }
        public class GroupList : ObservableCollection<Group>
        {
            public GroupList()
            {
                base.Add(new Group() { _groupname = "Group_1", _members = new List<String>() { "apple", "salad" }, _recipe = "Do this and do that" });
                base.Add(new Group() { _groupname = "Group_2", _members = new List<String>() { "banana", "onion" }, _recipe = "Don't do that and do this" });
            }
        }


    XAML
    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
    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
    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns<img src="images/smilies/icon_mad.gif" border="0" alt="" title=":x" class="inlineimg" />="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"
            Loaded="Window_Loaded">
        <Grid>
            <Label Margin="12,0,378,283" Content="Group"></Label>
            <Label Margin="190,0,200,283" Content="Members"></Label>
            <Label Margin="309,0,81,283" Content="Recipe"></Label>
            <TextBox Margin="309,34,12,12" DataContext="{Binding SelectedItem, ElementName=ListBox1}" Text="{Binding Path=_recipe, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <ListBox Margin="12,34,378,12" Name="ListBox1" SelectionMode="Single">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding _groupname}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <ListBox Margin="190,34,199,12" Name="ListBox2" SelectionMode="Multiple" SelectedValuePath="_name">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding _name}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.ContainerStyle>
                            <Style TargetType="{x:Type GroupItem}">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate>
                                            <Expander Header="{Binding Name}" IsExpanded="True">
                                                <ItemsPresenter />
                                            </Expander>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </GroupStyle.ContainerStyle>
                    </GroupStyle>
                </ListBox.GroupStyle>
            </ListBox>
        </Grid>
    </Window>

  2. #2
    Membre éprouvé
    pour faire cela il faut que tes items soient globalisés
    je te donne un exemple :
    imagine que tu ai une liste de tous les items ( avec instance)
    - banane A
    - poire B
    - farine C
    - oeuf D
    - ....

    dans recette (plutôt que ton groupe)
    - recette 1
    - banane A
    - farine C
    - recette 2
    - poire B
    - farine C
    - oeuf D


    et dans ton classement
    - fruit
    - banane A
    - poire C

    etc ...

    cela dit en travaillant avec des liste de chaîne ca peut simplifier
    si tu file ton projet exemple je te le corriger avec des liste de chaines c hyper simple

    en fait ce qu'il faut faire c'est mettre le selecteditems a la valeur de ce qui est dans la recette que tu as sélectionné pour chacune des listes
    meme si tu n'as pas l'element ca marchera
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  3. #3
    Expert confirmé
    bonjour Jayme65

    Cele peut être fait de diverse facons ,mais la meilleure c'est le MVVM ou direction de l'UI par les données avec filtrage des Views posées sur les observables collections Produits et Groupes...
    En voici un exemple que tu auras la bienveillance de compléter par un Class Command pour gérer le "Reset du Filtre de View" (il suffit de mettre SelectedGroup à null)...

    code behind.cs des Class Produit et Groupe
    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
    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
     
     public class Produit
        {
            public Groupe Groupe { get; set; }
            public string Code
            {
                get { return Groupe.Code ; }
            }
            public string NomGroupe 
            {
                get { return Groupe.Nom; }
            }
            public string Nom { get; set; }
        }
        public class Produits : ObservableCollection<Produit>
        {
            public Produits()
            {
                this.Add(new Produit {Groupe = new Groupe(){ Code="AA" }, Nom = "Orange"});
                this.Add(new Produit {Groupe = new Groupe(){ Code="BB" }, Nom = "Amande" });
                this.Add(new Produit {Groupe = new Groupe(){ Code="CC" }, Nom = "Raisin"});
                this.Add(new Produit { Groupe = new Groupe() { Code = "CC" }, Nom = "Poire" }); 
                this.Add(new Produit { Groupe = new Groupe() { Code = "AA" }, Nom = "Citron" });
                this.Add(new Produit { Groupe = new Groupe() { Code = "DD" }, Nom = "Cerise" });
            }
        }
     
     
    public class Groupe
        {
            public string Code { get; set; }
            public string Nom 
            {
                get {return this.ToString() ; }
     
            }
            public override string ToString()
            {
                return "Groupe "+ Code;
            }
        }
        public class Groupes : ObservableCollection<Groupe>
        {
            public Groupes()
            {
                this.Add(new Groupe { Code="AA" });
                this.Add(new Groupe { Code = "BB" });
                this.Add(new Groupe { Code = "DD" });
                this.Add(new Groupe { Code = "CC" });
            }
        }

    code behind.cs du Class VM ProduitModel:
    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
    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
     
     public class ProduitModel
        {
            public ProduitModel()
            {
                Produits = new Produits();
                Groupes = new Groupes();
                InitialiseViews();
            }
     
            private void InitialiseViews()
            {
                InitialiseProduitsView();
                InitialiseGroupesView();
            }
     
            private void InitialiseProduitsView()
            {
                ProduitsView = CollectionViewSource.GetDefaultView(Produits);
                ProduitsView.GroupDescriptions.Add(new PropertyGroupDescription("Groupe.Nom"));
            }
     
            private void InitialiseGroupesView()
            {
                GroupesView = CollectionViewSource.GetDefaultView(Groupes);
                GroupesView.SortDescriptions.Add(
                new SortDescription("Code", ListSortDirection.Ascending));
            }
            public Groupe SelectedGroupe
            {
                set
                {
                    if (value != null)
                    {
                       ProduitsView .Filter = o => ((Produit)o).Code == value.Code ;
                    }
                }
            }
     
            public ObservableCollection<Produit> Produits { get; private set; }
     
            public ObservableCollection<Groupe> Groupes { get; private set; }
            public ICollectionView ProduitsView { get; private set; }
     
            public ICollectionView GroupesView { get; private set; }
     
     
        }



    [CODE]

    code xaml du Form User:
    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
    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
     
    <Window x:Class="WpfEpicerie.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns<img src="images/smilies/icon_mad.gif" border="0" alt="" title=":x" class="inlineimg" />="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfEpicerie" 
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />roduitModel x:Key="model"/>
        </Window.Resources>
        <Grid 
            DataContext="{Binding Source={StaticResource model}}"
            Background="DarkGreen">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <TextBlock
                FontWeight="Bold" 
                Foreground="White"
                FontSize="20">Groupes</TextBlock>
            <ListBox Grid.Row="1" 
                     ItemsSource="{Binding Groupes}" 
                     DisplayMemberPath="Nom"
                     SelectedItem="{Binding SelectedGroupe,Mode=OneWayToSource}">
                <ListBox.GroupStyle>
                    <GroupStyle>
                        <GroupStyle.HeaderTemplate>
                            <DataTemplate>
                                <TextBlock
                                    Foreground="DarkGreen"
                                    Text="{Binding Nom}"
                                   FontStyle="Italic"/>
                            </DataTemplate>
                        </GroupStyle.HeaderTemplate>
                    </GroupStyle>
                </ListBox.GroupStyle>
     
     
            </ListBox>
     
            <TextBlock Grid.Column="1" FontWeight="Bold" 
                       Foreground="White"
                       FontSize="20">Produits</TextBlock>
            <ListBox 
                Grid.Column="1" Grid.Row="1" 
                ItemsSource="{Binding Produits}"
                DisplayMemberPath="Nom"/>
        </Grid>
    </Window>

    no code behind.cs....
    bon code...

  4. #4
    Membre du Club
    MABROUKI,
    Merci beaucoup pour ta réponse et le temps que tu y as consacré!
    Dans ton exemple cependant, une fois qu'un groupe a été sélectionné je n'ai pas accès à la liste complète des produits (pour pouvoir en rajouter ou en enlever)
    Ce que je voudrais, c'est que la liste produit contienne en permanence la liste de tout ce qui est disponible...et que les produits utilisés par le groupe soient sélectionné (mis en surbrillance), voire qu'une case à cocher à côté de leur nom soit sélectionnée!

  5. #5
    Membre du Club
    Citation Envoyé par ikeas Voir le message
    pour faire cela il faut que tes items soient globalisés
    je te donne un exemple :
    imagine que tu ai une liste de tous les items ( avec instance)
    - banane A
    - poire B
    - farine C
    - oeuf D
    - ....

    dans recette (plutôt que ton groupe)
    - recette 1
    - banane A
    - farine C
    - recette 2
    - poire B
    - farine C
    - oeuf D


    et dans ton classement
    - fruit
    - banane A
    - poire C

    etc ...

    cela dit en travaillant avec des liste de chaîne ca peut simplifier
    si tu file ton projet exemple je te le corriger avec des liste de chaines c hyper simple

    en fait ce qu'il faut faire c'est mettre le selecteditems a la valeur de ce qui est dans la recette que tu as sélectionné pour chacune des listes
    meme si tu n'as pas l'element ca marchera
    ikeas, merci pour ta réponse et ta proposition! Le projet correspond exactement à ce que j'ai posté mais je te le joint ici.
    Je me permet de te spécifier que je voudrais que la structure reste celle qui existe: il y a une liste de groupe et les groupes contiennent une recette...et une liste d'ingrédients. Cette liste d'ingrédient affiche toujours tous les ingrédients...et le groupe doit 'juste' marquer ceux utilisés comme 'highlighted', voire cocher une case en regard de leur nom!
    Merci!

  6. #6
    Membre éprouvé
    voila je t'ai refait une version peut être un peu plus compliqué
    mais full mvvm
    quand tu clique sur une recette tu vois les ingrédients coché
    j'ai changé les noms pour plus de lisibilité
    mais tu pourra les rechanger au besoin

    pour le moment tu ne peux pas changer les ingrédients d'une recette
    vu que le ConvertBack du selectionconverter n'est pas fait

    mais ca peut se faire aussi

    j'ai pris quelques liberté avec le mvvm pour les classements

    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

  7. #7
    Membre éprouvé
    voici la version complète
    * redesigné
    * avec le convert back fait

    le seul truc que j'ai pas peaufiné c'est l'interdiction de cocher quand il n'y a pas de recette sélectionné
    mais ça colle le check en erreur quand même

    après c un peu plus hard core puisque j'utilise
    des dependency property dans le converter
    le x:shared et le x:reference dans le xaml lol



    au final j'aurais pu me passer d'un multiconverter mais bon c'est pas non plus grave lol
    IKEAS : Finalement je crois que c'est dans ses faiblesses que l'on y trouve a la fois de la force et a la fois de la richesse...
    ----------------------------------------------------
    Si vous avez du taf en wpf & design d'application sympa, contactez moi !!!!
    http://ultimatecorp.eu/wpf/

###raw>template_hook.ano_emploi###