Search code examples
c#listclickpicturebox

Passing a List<Object> to the Click Handler when clicking PicutreBox in C# WinForm


I am trying to write a WinForm app that tracks my photos, where they are posted, and who is in them. I've created a SQL backend database with the information. I've created a model (person not programming) class to construct the object and then I've created a connection class that connects to the db and executes a query and creates a List with the values from the db.

I'm able to generate a group of images in the flowpanel layout that iterates through and grabs the photo. And from that same part of the Form1_Load I can output every element from the List to the console. What I am having an issue with is passing those values to the PictureBox1_Click handler. I can get the URL no problem because that is part of the PictureBox object, but I can't figure out how to get the whole Model object associated with a given photo I click on to send over. The intent is that when I click on a photo, the text labels I have in my layout should populate with name, location, date, etc values from the db.

I've tried passing the entire List to the click handler and that fails, I've tried overloading from the load event to pass to the click event and that gives me cast errors on the picture box.

    private void PictureBox1_Click(object sender, EventArgs e)
    {
        PictureBox p = (PictureBox)sender;


        string j = p.ImageLocation;
        MfNameTxt.Text = "Chris";
        MessageBox.Show("Clicked! " + j);
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        daoConn dc = new daoConn();
        List<Model> models = new List<Model>();
        string url;
        string fName;
        models = dc.GetAllModels();


        foreach (Model m in models)
        {
            int tempValue;
            tempValue = 1;
            PictureBox pb = new PictureBox();
            url = baseUrl + m.MhsUrl;
            fName = m.mFirstName;
            Size size = new Size(100, 100);
            pb.ImageLocation = url;
            pb.Size = size;
            pb.Click += new EventHandler(PictureBox1_Click);
            pb.SizeMode = PictureBoxSizeMode.Zoom;
            modelHsFlowLayout.Controls.Add(pb);
        }

    }

When I try pb.Click += new EventHandler((s, e1) => this.PictureBox1_Click(sender, e, tempValue)); just to send over a temp value and demonstrate I can pass something over there I get the case error: Message=Unable to cast object of type '_pictures_v2.Form1' to type 'System.Windows.Forms.PictureBox'.


Solution

  • It's because in the example code, sender is being passed through rather than passing s. Also you should pass in e1 rather than e.

    This would give the following code:

    pb.Click += new EventHandler((s, e1) => this.PictureBox1_Click(s, e1, tempValue))
    

    You can also make use of closures and rather than extracting your click handling code into a separate function it could all be done inline.

    For example:

    private void Form1_Load(object sender, EventArgs e)
        {
    
            daoConn dc = new daoConn();
            List<Model> models = new List<Model>();
            string url;
            string fName;
            models = dc.GetAllModels();
    
    
            foreach (Model m in models)
            {
                int tempValue;
                tempValue = 1;
                PictureBox pb = new PictureBox();
                url = baseUrl + m.MhsUrl;
                fName = m.mFirstName;
                Size size = new Size(100, 100);
                pb.ImageLocation = url;
                pb.Size = size;
                pb.Click += (s,clickEvent) => {
                    // You can use of pb directly here
                    // You also have access to things like models too.
                    string j = pb.ImageLocation;
                    MfNameTxt.Text = "Chris";
                    MessageBox.Show("Clicked! " + j);
                };
                pb.SizeMode = PictureBoxSizeMode.Zoom;
                modelHsFlowLayout.Controls.Add(pb);
            }
        }