Binding textBlock et image dans une listBox [Résolu]

Signaler
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
-
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
-
Bonjour,
J'ai une listbox dont chaque item est une "grid" composée d'une image et d'un label.

La listbox est rempli par binding sur une liste toute bête (List<> liste etc.)

Quand je sélectionne un item je voudrais afficher une image pour indiquer sur quel item je me trouve...

code pour le binding listBox - List<>:

<ListBox Height="Auto" HorizontalAlignment="Right" Margin="0,50,0,0" Name="listeListBox" VerticalAlignment="Stretch" Width="545" >            
            
<ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Image HorizontalAlignment="Left" Margin="0" Width="60" />
                        <Label Content="{Binding Name}" HorizontalAlignment="Left" Margin="60,0,0,0" Tag="{Binding FullName}" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>



code pour remplir la listBox (en précisant que je dois rajouter des items de temps à autre):

listeListBox.ItemsSource = null;
listeListBox.ItemsSource = liste; //ma fameuse liste générique!

J'ai essayé de mettre mon image via l'évènement SelectionChanged de la ListBox mais comment accéder au control "Image" du bon item?!?

J'espère avoir assez détaillé et que quelqu'un pourra m'aider!
A bientôt.
EDIT: Ajout de la coloration syntaxique.

3 réponses

Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
3
Donc comme dit plus haut, j'ai essayé et ça fonctionne!
Comme un peiti exemple vaut mieux qu'un long discour, j'ai fait une petite application qui explique ce que je voulais faire...


Le xaml d'abord

<Window x:Class="BindingTest.MainWindow"
        xmlns="[http://schemas.microsoft.com/winfx/2006/xaml/presentation]"
        xmlns:x="[http://schemas.microsoft.com/winfx/2006/xaml]"
        Title="MainWindow" Height="400" Width="320" Loaded="Window_Loaded">
    
    <Grid>
        
        <ListBox HorizontalAlignment="Stretch" Margin="0,50,0,0" Name="MaListBox" VerticalAlignment="Stretch" Grid.ColumnSpan="2" PreviewMouseDown="MaListBox_PreviewMouseDown" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Image Height="15" HorizontalAlignment="Left" Margin="0" Source="{Binding Img}" VerticalAlignment="Center" Width="50" />
                        <Label Content="{Binding NomItem}" HorizontalAlignment="Stretch" Margin="60,0,0,0" VerticalAlignment="Top" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <Button Content="Item suivant" HorizontalAlignment="Center" Margin="0,20,120,0" Name="nextButton" VerticalAlignment="Top" Width="100" Height="20" Click="nextButton_Click"/>
        <Button Content="Item précédent" HorizontalAlignment="Center" Margin="120,20,0,0" Name="previousButton" VerticalAlignment="Top" Width="100" Height="20" Click="previousButton_Click"/>

    </Grid>
</Window>



Ensuite la classe:

using System.ComponentModel;

namespace BindingTest
{
    class TestPropertyChanged : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;   //Evènement qui va faire en sorte que les changements d'image seront pris en compte
        
        //Les propriétés
        public string NomItem { get; set; }

        private string _Img;
        public string Img
        {
            get
            {
                return _Img;
            }
            set
            {
                _Img = value;
                MyPropertyChanged("Img"); //la propriété de ma classe que le "binding" influencera
            }
        }

        //constructeur
        public TestPropertyChanged(string nItem, string itemSelection)
        {
            NomItem = nItem;
            _Img = itemSelection;
        }

        //méthode qui est applée en cas de changement de la propriété
        protected void MyPropertyChanged(string propertyName)
        {
            if (PropertyChanged == null)
            {
                return;
            }
            else
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}



Et enfin le corps du programme:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;

namespace BindingTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //chemin complet de l'image
        const string sourceImage = @"C:\Users\Thomas\Desktop\BindingTest\BindingTest\Images\fleche_droite.png";

        List<TestPropertyChanged> liste;    //la liste... rien à ajouter!
        int index;                          //numéro de l'item dans la liste


        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            index = 0;

            liste = new List<TestPropertyChanged>();
            liste.Add(new TestPropertyChanged("Item 01", sourceImage));     //La logique veut commencer à sélectionner les item par le début donc chemin de l'image symbolisant la selection!
            liste.Add(new TestPropertyChanged("Item 02", null));            //Ensuite, null (ce qui n'affichera pas l'image!!!).
            liste.Add(new TestPropertyChanged("Item 03", null));
            liste.Add(new TestPropertyChanged("Item 04", null));
            liste.Add(new TestPropertyChanged("Item 05", null));
            liste.Add(new TestPropertyChanged("Item 06", null));
            liste.Add(new TestPropertyChanged("Item 07", null));
            liste.Add(new TestPropertyChanged("Item 08", null));
            liste.Add(new TestPropertyChanged("Item 09", null));
            liste.Add(new TestPropertyChanged("Item 10", null));

            MaListBox.ItemsSource = liste;
        }


        private void nextButton_Click(object sender, RoutedEventArgs e)
        {
            liste[index].Img = null;                                            //on chage d'item, donc plus besoin d'afficher l'image
            index = (index < MaListBox.Items.Count - 1) ? index + 1 : 0;        //on incrémente l'indice servant à choisir les item dans la liste (si on arrive au bout de la liste, on revien au début)
            liste[index].Img = sourceImage;                                     //affichage de l'image à l'indice suivant
        }
        private void previousButton_Click(object sender, RoutedEventArgs e)
        {
            //même principe que pour "nextButton_Click"

            liste[index].Img = null;
            index = (index == 0) ? MaListBox.Items.Count - 1 : index - 1;      
            liste[index].Img = sourceImage;  
        }


        private void MaListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            //Come je veux symboliser la sélection à ma manière, j'annule l'évènement natif de la listBox
            e.Handled = true;
        }        
    }
}


EDIT: Précision du langage dans la coloration syntaxique.
Messages postés
16037
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
17 juin 2021
551
Bonjour, ce qu'il faut c'est que la classe qui remplit ta liste (que tu n'as pas montrée) ait une propriété qui permettra au template de charger la bonne image, cette propriété doit être de type BitmapImage et avoir au préalable été chargée de l'image correspondante à ton item.

            Uri uri = new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg");
            BitmapImage img = new BitmapImage(uri);//chargement de la propriété


et le template
        <Image  HorizontalAlignment="Left" Height="100" Margin="1381,164,0,0" VerticalAlignment="Top" Width="100" Source="{Binding MonImage}"/>

Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
3
Re,
En fait je n'avais pas pensé que que l'astuce se trouverai dans la classe (je me suis surement bourré le crane et ai forcément zappé un détail!).

Toujours est-il qu'entre temps j'ai modifié ma classe et en suis arrivé pratiquement à la même chose que toi; ma variable est de type string et contient le chemin de l'image à afficher ou null (selon qu'il y ai ou non besoin d'afficher)!

J'ai pourtant encore une question, pour afficher la modification je suis obligé de recharger mon "ItemsSource"... Est-ce que je fais bien ou y a-t-il une façon de procéder moins "triche"?

Encore merci!
Messages postés
16037
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
17 juin 2021
551 >
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017

Il faut que ta classe implémente INotifyPropertyChanged, et bien sûr que les propriétés concernées alertent de leur changement. Le binding se mettra (normalement) à jour tout seul
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
3
D'accord, je vais essayer ça...
Je te remercie et joyeuse Pâques!
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Statut
Membre
Dernière intervention
25 juin 2017
3
Re-bonjour,
Et bien en fait j'ai trouvé...
C'est dans ma classe que ça se passe!

En gros j'utilise une variable par élément à "binder". En l'occurence j'ai rajouté une variable de type string dans ma classe qui correspond au chemin de l'image (contient null si pas pas besoin d'afficher et contient le chemin en question si besoin d'afficher!)...

Ensuite je jongle:

itemssource = null;
modification de la variable "source" (class.variable = chemin;) puis
itemssource = liste;

J'explique en vitesse mais je peux toujours détailler si besoin!
Et si il y a un autre moyen moins "triche", je suis preneur quand-même!

Voilà à bientôt!
--