Binding textBlock et image dans une listBox

Résolu
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 - Modifié par Whismeril le 5/04/2015 à 13:28
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 - 6 avril 2015 à 15:16
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.
A voir également:

3 réponses

moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
Modifié par Whismeril le 6/04/2015 à 15:35
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.
1
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
5 avril 2015 à 13:56
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}"/>

0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
5 avril 2015 à 14:06
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!
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656 > moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017
5 avril 2015 à 17:34
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
0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
5 avril 2015 à 22:21
D'accord, je vais essayer ça...
Je te remercie et joyeuse Pâques!
0
moi411 Messages postés 179 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
5 avril 2015 à 13:56
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!
--
0
Rejoignez-nous