c# 如何创建按钮并稍后通过 ID 删除它们

c# How to create buttons and delete them later by an ID

我正在努力创建这个生成好友请求的脚本。我需要专门为每个按钮和标签添加一个 id,以便在用户单击接受或拒绝按钮时将其删除。

Button reqAccept;
Button reqReject;
Label reqUserName;

private void loadFriendRequests()
{
    using (SqlConnection connection = new SqlConnection(con))
    {
        using (SqlCommand cmd = new SqlCommand("Select UserFirstName, UserLastName, FriendEmail From PendingRequests Where FriendEmail = @fe", connection))
        {
            connection.Open();
            cmd.Parameters.AddWithValue("@fe", Properties.Settings.Default.Email);
            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                i = 0;
                while (dr.Read())
                {
                    i++;
                    foreach (object request in i.ToString())
                    {
                        Label userName = new Label();
                        Button accept = new Button();
                        Button reject = new Button();

                        accept.Click += Accept_Click;
                        reject.Click += Reject_Click;

                        userName.Text = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(dr["UserFirstName"].ToString() + " " + dr["UserLastName"].ToString());

                        accept.Text = "Accept";
                        reject.Text = "Reject";

                        friendRequestPanel.Controls.Add(userName);
                        friendRequestPanel.Controls.Add(accept);
                        friendRequestPanel.Controls.Add(reject);

                        reqAccept = accept;
                        reqReject = reject;
                        reqUserName = userName;
                    }
                }
            }
        }
    }
    Requests.Start();
}
private void Reject_Click(object sender, EventArgs e)
{
    friendRequestPanel.Controls.Remove(reqUserName);
    friendRequestPanel.Controls.Remove(reqAccept);
    friendRequestPanel.Controls.Remove(reqReject);

    updateFriendRequestDatabase(2);
}
private void Accept_Click(object sender, EventArgs e)
{
    friendRequestPanel.Controls.Remove(reqUserName);
    friendRequestPanel.Controls.Remove(reqAccept);
    friendRequestPanel.Controls.Remove(reqReject);

    updateFriendRequestDatabase(1);
}

代码的作用: 上面的代码正在选择与用户电子邮件相同的请求,对于每个好友请求,它将通过使用标签和 2 个接受或拒绝按钮将其添加到 'FlowLayourPanel'。

这是 GUI 的样子:GUI

当用户点击一个按钮时,它显然会转到事件处理程序,但我如何识别按下了哪个按钮?

它需要像这样:

friendRequestPanel.Controls.Remove(reqUserName##ID##);

要做的第一件事是从您的查询中检索唯一标识您的数据的值。假设您的 PendingRequest table 有一个 IDRequest 那么您的查询可以更改为

  using (SqlCommand cmd = new SqlCommand(@"Select IDRequest, UserFirstName, 
                      UserLastName, FriendEmail 
                      From PendingRequests 
                      Where FriendEmail = @fe", connection))

现在,当您动态创建控件时,您还将该 ID 添加到由该记录创建的每个控件的标签 属性

foreach (object request in i.ToString())
{
    Label userName = new Label();
    Button accept = new Button();
    Button reject = new Button();

    int idRequest = Convert.ToInt32(dr["IDRequest"]);
    userName.Tag = idRequest;
    accept.Tag = idRequest;
    reject.Tag = idRequest;
    ....

最后,在您的点击事件中,您可以使用如下代码检索按钮和标签的确切实例

private void Reject_Click(object sender, EventArgs e)
{
    Button c = sender as Button;
    int idRequest = Convert.ToInt32(c.Tag);
    var ctrls = friendRequestPanel.Controls
                                  .Cast<Control>()
                                  .Where(x => x.Tag != null &&
                                         Convert.ToInt32(x.Tag) == idRequest)
                                  .ToList();
    foreach(Control ct in ctrls)
    {
          friendRequestPanel.Controls.Remove(ct);
          ct.Dispose();
    }
    updateFriendRequestDatabase(2);
}

请注意,如果您从 Controls 集合中删除控件,则不应忘记对其进行处置。

@Steve 回答得很好。他已经向您展示了如何修复当前代码。

我想向您建议一种更好的方式来构建您当前的代码,这样它看起来更清晰并且您可以更好地控制好友请求功能。如果您有兴趣,请进一步阅读。如果您的截止日期很紧,请忽略 :)。

如果我处在你的位置,我会创建一个用户控件来表示个人好友请求,并在 accept/reject 的情况下使用事件通知主窗体,以便它可以从 panel/list.这样主窗体代码(设计器+代码隐藏)将变得更易于阅读和理解。

FriendRequestControl

这将是标准 UserControl,其中包含 1 个 Label(用于显示朋友的姓名和 2 个 Buttons 接受和拒绝。

public partial class FriendRequestControl : UserControl
{
    public event EventHandler Accepted;
    public event EventHandler Rejected;

    public FriendRequestControl()
    {
        InitializeComponent();
    }

    public int RequestId { get; set; }
    public string FriendName { set { lblFriend.Text = value; } } // TODO add empty/null checks on value

    private void Accept_Click(object sender, EventArgs e)
    {
        UpdateRequest(1);
        OnAccepted();
    }

    private void Reject_Click(object sender, EventArgs e)
    {
        UpdateRequest(2);
        OnRejected();
    }

    private bool UpdateRequest(int flag)
    {
        // Update db using RequestId and flag
        // TODO Return True/False based if update succeeds
        return true; 
    }

    private void OnAccepted()
    {
        var acceptedHandler = Accepted;
        if (acceptedHandler != null)
        {
            acceptedHandler(this, EventArgs.Empty);
        }
    }

    private void OnRejected()
    {
        var rejectedHandler = Rejected;
        if (rejectedHandler != null)
        {
            rejectedHandler(this, EventArgs.Empty);
        }
    }
}

主窗体

private void Form1_Load(object sender, EventArgs e)
{
    // Showing just 1 request here
    var friendRequest = new FriendRequestControl
    {
        RequestId = 100, // As Steve mentioned, you db must return this.
        FriendName = "Friend 1"
    };

    friendRequest.Accepted += FriendRequest_Accepted;
    friendRequest.Rejected += FriendRequest_Rejected;

    flowLayoutPanel1.Controls.Add(friendRequest);
}

private void FriendRequest_Rejected(object sender, EventArgs e)
{
    var friendRequest = sender as FriendRequestControl;
    flowLayoutPanel1.Controls.Remove(friendRequest);
}

private void FriendRequest_Accepted(object sender, EventArgs e)
{
    var friendRequest = sender as FriendRequestControl;
    flowLayoutPanel1.Controls.Remove(friendRequest);
}