Search code examples
c#winformseventspicturebox

Create a picturebox_clicked event for each picturebox created


 private Form1 form1 { get; set; }
    readonly HttpClient httpClient = new();
    public static string FolderPath = @".\Storage";
    public static int picNum = 0;
    public static List<string> outofScopeURL = new List<string>();
    
    private async void Detailed_View_Load_1(object sender, EventArgs e)
    {
        DirectoryInfo directory = new(FolderPath);
        FileInfo[] files = directory.GetFiles();
        string[] FileFormats = { ".png", ".jpg", ".jpeg", ".txt" };
        for (int pictureCreator = 0; pictureCreator < files.Length; pictureCreator++)
        {
            FileInfo file = files[pictureCreator];
            if (file.FullName.EndsWith(FileFormats[3])) 
            {
                string url = File.ReadAllText(file.FullName);
                if (url != null)
                {
                    try
                    {
                        Image gif = Image.FromStream(await httpClient.GetStreamAsync(url));
                        PictureBox picture = new PictureBox
                        {
                            Name = url,
                            Size = new(38, 38),
                            Image = gif,
                            Location = new((gif.Width * pictureCreator), 0),
                            SizeMode = PictureBoxSizeMode.Zoom
                        };
                        this.Controls.Add(picture);
                        MessageBox.Show(picture.Name);
                        outofScopeURL.Add(url);
                        picture.Click += Picture_Click;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
                picNum++;
            }
        }
    }

What I'm trying to achieve: I'm trying to look in a specific directory for text files, then I want to read the files and extract the URL present in them. After I got all of the URLs of all the text files present in my folder, I added them into a list so I could use them with their respective picturebox

For example, when URL1 has picture1 and URL2 has picture2, I want to set the text of the clipboard to URL1 when picturebox1 that has picture1 applied to it is clicked.

What I have tried: I have tried making a new picturebox_Clicked event in the pictureCreator for loop but the problem is that the event is always applied to the last picturebox created.

Any help is much appreciated.


Solution

  • Your question is about creating a picturebox_clicked event for each picturebox created.

    The code you posted seems to be doing that but as mentioned in the comments, casting the sender argument would be the key to making event useful. Consider a click handler implemented similar to this:

    private void onAnyPictureBoxClick(object? sender, EventArgs e)
    {
        if(sender is PictureBox pictureBox)
        {
            var builder = new List<string>();
            builder.Add($"Name: {pictureBox.Name}");
            builder.Add($"Tag: {pictureBox.Tag}");
            builder.Add($"Image Location: {pictureBox.ImageLocation}");
            MessageBox.Show(string.Join(Environment.NewLine, builder));
        }
    }
    

    Now give it a test (simulating the part where the URLs are already collected from the local store).

    public partial class MainForm : Form
    {
        public MainForm() =>InitializeComponent();
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            int id = 0;
            // Here we have "already read" the URLs from the local store.
            foreach (var url in new string[] 
            {
                "https://i.sstatic.net/eSiWr.png",
                "https://i.sstatic.net/o5dmA.png",
                "https://i.sstatic.net/aqAuN.png",
            })
            {
                var dynamicPB = new PictureBox
                {
                    Width = flowLayoutPanel.Width - SystemInformation.VerticalScrollBarWidth,
                    Height = 200,
                    SizeMode = PictureBoxSizeMode.Zoom,
                    BackColor = Color.Azure,
                    // In this case, the url is already stored here...
                    ImageLocation = url,
                    // ...but here are a couple of other ID options.
                    Name = $"pictureBox{++id}",
                    Tag = $"Tag Identifier {id}",
                    Padding = new Padding(10),
                };
                dynamicPB.Click += onAnyPictureBoxClick;
                flowLayoutPanel.Controls.Add(dynamicPB);
            }
        }
        .
        .
        .
    }
    

    screenshot