c# How to create buttons and delete them later by

2019-02-28 05:34发布

I'm struggling to create this script where it generates friend requests. I need to specifically add an id to each button and label so I can remove it when the user clicks either the accept or reject button.

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

What the code is doing: The code above is selecting requests that are the same as the user's email and for every friend request there is, it will add it to 'FlowLayourPanel' by using a label and 2 buttons to either accept or reject.

This is what the GUI looks like: GUI

When the user clicks a button it will obviously go to the event handler but how do I identify which button was pressed?

It needs to be something like:

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

2条回答
We Are One
2楼-- · 2019-02-28 05:37

The first thing to do is to retrieve from your query the value that uniquely identifies your data. Suppose that your PendingRequest table has an IDRequest then your query could be changed to

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

Now when you create your controls dynamically you add also that ID to the Tag property of every control created by that record

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;
    ....

Finally in your click event you could retrieve the exact instance of the buttons and label using a code like this

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

Notice that if you remove the control from the Controls collection you should not forget to Dispose it.

查看更多
ゆ 、 Hurt°
3楼-- · 2019-02-28 05:59

@Steve has answered it all well. He has already shown you how to fix your current code.

I want to suggest you a better way to structure your current code, so that it looks cleaner and you have more control over the friend request functionality. If you are interested, read further. If you are on tight deadlines then ignore :).

If I was in your place, I would create a user control to represent individual friend request and use events to notify main form in case of accept/reject so that it can remove the request from panel/list. This way main form code (designer + code behind) will become cleaner to read and understand.

FriendRequestControl

This would be standard UserControl which has contains 1 Label (for displaying friend's name and 2 Buttons accept and reject.

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

Main Form

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);
}
查看更多
登录 后发表回答