Search code examples
c#wpfbindinglistbox

Display images in ListBox


I loading various images in run time and I want to show them in list box (small images, then the user should click on one of them and show him in real size).

My code is:

public partial class MainWindow : Window
{
    int imageNumber = 0;
    public List<String> ImagePath = new List<String>();

    public MainWindow()
    {
        InitializeComponent();
        lb_Images.ItemsSource = ImagePath;
    }

    private void bu_addImage_Click(object sender, RoutedEventArgs e)
    {
        addImageToListBox();
    }

    private void addImageToListBox()
    {
        imageNumber++;
        if (imageNumber == 4) imageNumber = 0;
        string directoryPath = AppDomain.CurrentDomain.BaseDirectory;

        // load input image
        string ImageFilename = directoryPath + "img";
        ImageFilename += imageNumber.ToString();
        ImageFilename += ".jpg";

        ImagePath.Add(ImageFilename);
    }
}

and the xaml is:

<Window x:Class="forQuestionWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="216" Width="519">

    <Window.Resources>
        <DataTemplate x:Key="ImageGalleryDataTemplate">
            <Grid>
                <Border BorderBrush="#FFFF9800" BorderThickness="1"  Width="120" Height="120" Padding="5" Margin="5" CornerRadius="6">
                    <!--Bind Image Path in Image Control-->
                    <Image Source="{Binding ImagePath}" Stretch="Fill"  HorizontalAlignment="Center">
                        <!--View Large Image on Image Control Tooltip-->
                        <Image.ToolTip>
                            <Grid>
                                <Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Center" Height="200" Width="200"></Image>
                            </Grid>
                        </Image.ToolTip>
                    </Image>
                </Border>
            </Grid>
        </DataTemplate>

        <ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
            <!--Display Images on UniformGrid Panel-->
            <UniformGrid Rows="1" Columns="25" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
        </ItemsPanelTemplate>
    </Window.Resources>
    
    <Grid>
        <Canvas Height="177" HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top" Width="497">
            
            <ListBox Canvas.Left="6" Canvas.Top="5" Height="166" Name="lb_Images" Width="441"
                     BorderBrush="{x:Null}" DataContext="{Binding Source={StaticResource ImageGalleryDataTemplate}}"
                     ItemsSource="{Binding Source={StaticResource ImageGalleryItemsPanelTemplate}}">
            </ListBox>
            
            <Button Canvas.Left="453" Canvas.Top="26" Content="Add" Height="64" Name="bu_addImage" Width="38" Click="bu_addImage_Click" />
        </Canvas>
    </Grid>
</Window>

I know that the list box updated when I add image path to the list because if I debug I found some items under lb_Images.items, but I show nothing.


Solution

  • Some notes

    • DataContext for ListBox it's not necessary, then you set ItemSource. Instead of set the ItemTemplate

    • In DataTemplate remove the {Binding ImagePath}, instead of write {Binding}, because in this case the elements of the DataTemplate inherit DataContext.

    • When you add new items to ListBox.Items, you must call ListBox.Items.Refresh() or use the ObservableCollection<T>, because:

    ObservableCollection represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.

    Try this example:

    XAML

    <Window.Resources>
        <DataTemplate x:Key="ImageGalleryDataTemplate">
            <Grid>
                <Border BorderBrush="#FFFF9800" BorderThickness="1"  Width="120" Height="120" Padding="5" Margin="5" CornerRadius="6">
                    <Image Source="{Binding}" Stretch="Fill"  HorizontalAlignment="Center">
                        <Image.ToolTip>
                            <Grid>
                                <Image Source="{Binding}" Stretch="Fill" HorizontalAlignment="Center" Height="200" Width="200" />
                            </Grid>
                        </Image.ToolTip>
                    </Image>
                </Border>
            </Grid>
        </DataTemplate>
    
        <ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
            <UniformGrid Rows="1" Columns="25" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
        </ItemsPanelTemplate>
    </Window.Resources>
    
    <Grid>
        <Canvas Height="177" HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top" Width="497">
    
            <ListBox Canvas.Left="6" Canvas.Top="5" Height="166" Name="lb_Images" Width="441"  
                     ItemTemplate="{StaticResource ImageGalleryDataTemplate}"
                     ItemsSource="{Binding Path=ImagePath}">
            </ListBox>
    
            <Button Canvas.Left="453" Canvas.Top="26" Content="Add" Height="64" Name="bu_addImage" Width="38" Click="bu_addImage_Click" />
        </Canvas>
    </Grid>
    

    Code-behind

    public partial class MainWindow : Window
    {
        int imageNumber = 0;
        public List<String> ImagePath = new List<String>();
    
        public MainWindow()
        {
            InitializeComponent();
            lb_Images.ItemsSource = ImagePath;
        }
    
        private void bu_addImage_Click(object sender, RoutedEventArgs e)
        {
            addImageToListBox();
        }
    
        private void addImageToListBox()
        {
            imageNumber++;
            if (imageNumber == 4) imageNumber = 0;
            string directoryPath = AppDomain.CurrentDomain.BaseDirectory;
    
            // load input image
            string ImageFilename = directoryPath + "img";
            ImageFilename += imageNumber.ToString();
            ImageFilename += ".jpg";
    
            ImagePath.Add(ImageFilename); 
    
            lb_Images.Items.Refresh();
        }
    }