Search code examples
c#imagelistviewpictureboximagelist

C# Going back to previous image in listview and displaying it in Picturebox


I’m trying to select the previous image in the list view and display it in the picture box on the right. I’m using _imageIndex to keep track of what’s in the picture box currently and if it’s less than the image list length then I select the image in the list view and using the _imageIndex counter to access the image.

But it’s like it’s not getting the image index at all. It just keeps reading it at 0 and decrementing it to negative 1 and return an error when I click btnPrevious again.

System.ArgumentOutOfRangeException: 'InvalidArgument=Value of '-1' is not valid for 'index'.
Parameter name: index'

I know I set it to _imageIndex to 0 in the mnuOpen_Click event. Other than that I don’t know how to solve this. For clarity here is an image of the GUI. Ideas please?

public partial class Form1 : Form
{
    string _big_fileName;
    int _counter = 0;
    int _imageIndex;

    public Form1()
    {            
        InitializeComponent();
    }

    //Displays larger instance of selected image in picture box.
    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        //FOR i is less than the first image.
        for (int i = 0; i < listView1.SelectedItems.Count;i++)
        {                
            //GET filename from listview and store in index.
            _big_fileName = listView1.SelectedItems[i].Text;
            //Create larger instance of image.
            pictureBox1.Image = Image.FromFile(_big_fileName);
            //Fill panel to the width and height of picture box.
            panel1.AutoScrollMinSize = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height);
        }
    }

    private void mnuOpen_Click(object sender, EventArgs e)
    {            
        loadImageList();
        _imageIndex = 0;
    }

    private void btnPrevious_Click(object sender, EventArgs e)
    {
        if (pictureBox1.Image != null)
        {                
            //IF Image is less than Image list size.
            if (_imageIndex < imageList1.Images.Count)
            {
                //SELECT  listview items with counter.
                listView1.Items[_imageIndex].Selected = true;
                //GO to previous entry.
                _imageIndex--;
            }
        }

        else
        {
            MessageBox.Show("No image.");
        }
    }

    //Cycle to next image in image list and display in Picturebox.
    private void btnNext_Click(object sender, EventArgs e)
    {
        if(pictureBox1.Image != null)
        {
            //IF Image is less than Image list size.
            if (_imageIndex < imageList1.Images.Count)
            {
                listView1.Items[_imageIndex].Selected = true;

                _imageIndex++;
            }
        }

        else
        {
            MessageBox.Show("No image.");
        }
    }

    private void loadImageList()
    {
        imageList1.Images.Clear();
        listView1.Clear();

        oFD1.InitialDirectory = "C:\\";
        oFD1.Title = "Open an Image File";
        oFD1.Filter = "JPEGS|*.jpg|GIFS|*.gif|PNGS|*.png|BMPS|*.bmp";

        //Open Dialog Box.
        var oldResults = oFD1.ShowDialog();

        if (oldResults == DialogResult.Cancel)
        {
            return;
        }

        try
        {
            //GET amount of filenames.
            int num_of_files = oFD1.FileNames.Length;
            //Store filenames in string array.
            string[] arryFilePaths = new string[num_of_files];


            //FOREACH filename in the file.
            foreach (string single_file in oFD1.FileNames)
            {
                //ACCESS array using _counter to find file.
                arryFilePaths[_counter] = single_file;
                //CREATE image in memory and add image to image list.
                imageList1.Images.Add(Image.FromFile(single_file));
                _counter++;
            }
            //BIND image list to listview.
            listView1.LargeImageList = imageList1;


            for (int i = 0; i < _counter; i++)
            {
                //DISPLAY filename and image from image index param. 
                listView1.Items.Add(arryFilePaths[i], i);
            }
        }

        catch (Exception ex)
        {
            MessageBox.Show("Error " + ex.Message);
        }
    }      
}

Solution

  • First of all, you're not setting _imageIndex anywhere, except in btnPrevious_Click, where you set it to 0.

    You need to set it to selected index, in SelectedIndexChanged method, like this (notice the last line added to your previous code):

    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //FOR i is less than the first image.
            for (int i = 0; i < listView1.SelectedItems.Count; i++)
            {
                //GET filename from listview and store in index.
                _big_fileName = listView1.SelectedItems[i].Text;
                //Create larger instance of image.
                pictureBox1.Image = Image.FromFile(_big_fileName);
                //Fill panel to the width and height of picture box.
                panel1.AutoScrollMinSize = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height);
                _imageIndex = listView1.SelectedIndices[0];
            }
        }
    

    Next, in btnPreviousClick, you need to make few changes:

    private void btnPrevious_Click(object sender, EventArgs e)
        {
            if (pictureBox1.Image != null)
            {
                //IF Image is less than Image list size.
                if (_imageIndex >= 0 && _imageIndex < imageList1.Images.Count)
                {
                    //De-select current item
                    listView1.Items[_imageIndex].Selected = false;
                    //GO to previous entry.
                    _imageIndex--;
                    //Select new item
                    if(_imageIndex>=0){
                       listView1.Items[_imageIndex].Selected = true;
                       listView1.Select();
                    }
                }
            }
            else
            {
                MessageBox.Show("No image.");
            }
        }
    

    It's necessary to call Select() method on listView1. Biggest issue was that you didn't set _imageIndex though.

    Hope this is what you were looking for :)

    Best regards,