为创建的每个图片框创建一个picturebox_clicked事件

Create a picturebox_clicked event for each picturebox created

提问人:Ahmed Sherif 提问时间:1/27/2023 更新时间:1/27/2023 访问量:53

问:

 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++;
            }
        }
    }

我想要实现的目标:我正在尝试在特定目录中查找文本文件,然后我想读取文件并提取其中存在的 URL。 在我获得文件夹中所有文本文件的所有 URL 后,我将它们添加到一个列表中,以便我可以将它们与各自的图片框一起使用

例如,当 URL1 具有 picture1 而 URL2 具有 picture2 时,当单击应用了 picture1 的 picturebox1 时,我想将剪贴板的文本设置为 URL1。

我试过什么:我尝试在 pictureCreator for 循环中创建一个新的 picturebox_Clicked 事件,但问题是该事件始终应用于创建的最后一个图片框。

任何帮助都非常感谢。

C# WinForms 事件 PictureBox

评论

2赞 Reza Aghaei 1/27/2023
sender的事件是点击的,你可以在创建控件时把一些东西放在它的标签上,然后再读取它。或者,您可以只为控件分配一些名称,并使用 a 来存储其他数据。字典的键是 pictureBoxName,值可以像 url 一样简单,也可以是包含任何相关信息的复杂对象。PictureBoxDictionary<string, something>
1赞 Reza Aghaei 1/27/2023
顺便说一句,如果您分配 ImageLocation 或使用它的 LoadAsync 方法,PictureBox 可以加载图像。看看这篇文章:将图像从 Url 异步加载到 PictureBox。因此,不需要 Web 客户端,除非您有其他要求,例如身份验证等。
1赞 Reza Aghaei 1/27/2023
另一项改进:无需自行排列控件,只需使用 TableLayoutPanel 或 FLowLayoutPanel。

答:

1赞 IV. 1/27/2023 #1

您的问题是关于为每个创建的图片框创建一个picturebox_clicked事件

您发布的代码似乎正在这样做,但正如评论中提到的,转换参数将是使事件有用的关键。考虑一个实现与此类似的点击处理程序:sender

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));
    }
}

现在给它一个测试(模拟已经从本地存储中收集 URL 的部分)。

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.stack.imgur.com/eSiWr.png",
            "https://i.stack.imgur.com/o5dmA.png",
            "https://i.stack.imgur.com/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