如何从窗体中的用户控件动态添加和删除用户控件

本文关键字:用户 控件 动态 删除 添加 窗体 | 更新日期: 2023-09-27 18:36:07

我正在努力在表单中添加动态并删除用户控件。我有一个表单,在我的表单中,我有一个面板,它有一个静态控件。

我试图实现的是将用户控件添加到面板中。虽然添加起来很容易,但我知道有更好的方法可以做到这一点。

通过单击窗体中的按钮将用户控件添加到我的面板。

private void btnadd_Click(object sender, EventArgs e)
{
    UserControl1 usr = new UserControl1
    pnlUI.SuspendLayout();
    pnlUI.Controls.Clear();
    pnlUI.Controls.Add(usr);
    pnlUI.ResumeLayout(false);
}
// This one adds it and clearing the control that was already in the panel of the form.

现在,我在这里堆积了添加的用户控件,并尝试再次显示面板中已删除或清除的控件。

在我的用户控件

上,我正在尝试释放用户控件的后退按钮上有一个后退按钮。但在那之后,原始控件不再存在,面板已经是空的。

有什么建议吗?

如何从窗体中的用户控件动态添加和删除用户控件

可以将实例变量添加到窗体中以跟踪以前的控件。这假定面板中只有一个控件。

在您的班级中:

private Control _previousPanelContent;

然后在您的方法中:

private void btnadd_Click(object sender, EventArgs e)
{
    UserControl1 usr = new UserControl1();
    pnlUI.SuspendLayout();
    // check if there's already content in the panel, if so, keep a reference.
    if (pnlUI.Controls.Count > 0)
    {
        _previousPanelContent = pnlUI.Controls[0];
        pnlUI.Controls.Clear();
    }
    pnlUI.Controls.Add(usr);
    pnlUI.ResumeLayout(false);
}

然后稍后当您想返回时:

    pnlUI.SuspendLayout();
    pnlUI.Controls.Clear();
    // if the previous content was set, add it back to the panel 
    if (_previousPanelContent != null)
    {
        pnlUI.Controls.Add(_previousPanelContent);
    }
    pnlUI.ResumeLayout(false);

下面是上面注释中提到的事件方法的简单示例。

具有"后退"事件的用户控件:

public partial class UserControl1 : UserControl
{
    public event dlgBack Back;
    private UserControl1 _previous = null;
    public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
    public UserControl1(UserControl1 previous)
    {
        InitializeComponent();
        this._previous = previous;
    }
    private void btnBack_Click(object sender, EventArgs e)
    {
        if (Back != null)
        {
            Back(this, _previous);
        }
    }
}

然后,窗体创建用户控件并订阅事件:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void btnAdd_Click(object sender, EventArgs e)
    {
        UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
        UserControl1 usr = new UserControl1(prevUsr);
        usr.Back += usr_Back;
        pnlUI.Controls.Clear();
        pnlUI.Controls.Add(usr);
    }
    void usr_Back(UserControl1 sender, UserControl1 previous)
    {
        pnlUI.Controls.Remove(sender);
        if (previous != null)
        {
            pnlUI.Controls.Add(previous);
        }
    }
}

在按钮回调函数声明用户控件(回调函数是在运行时发生事件(如按钮单击等)时调用的函数)。这意味着无法在其外部访问包含用户控件的变量,因此您无法从另一个回调函数使用它。

而不是这样做:

private void btnadd_Click(object sender, EventArgs e)
{
    //This is not accessible outside the callback function.
    UserControl1 usr = new UserControl1();
    pnlUI.SuspendLayout();
    pnlUI.Controls.Clear();
    pnlUI.Controls.Add(usr);
    pnlUI.ResumeLayout(false);
}

尝试声明一个将保存用户控件的属性,以便在其他地方使用它:

//Declare a private property - you can adjust the access level of course,
//depending on what you need.
//You can even declare a field variable for the same cause,such as
//private UserControl _myUserControl;
//This declaration is in the class body.
private UserControl MyUserControl { get; set; }
//Your addition callback function.
private void btnadd_Click(object sender, EventArgs e)
{
    //The user control is now assigned to the property.
    MyUserControl = new UserControl1();
    pnlUI.SuspendLayout();
    pnlUI.Controls.Clear();
    pnlUI.Controls.Add(MyUserControl);
    pnlUI.ResumeLayout(false);
}
//Your removal callback function.
private void btnremove_Click(object sender, EventArgs e)
{
    //...
    //Use the property value here.
    pnlUI.Controls.Remove(MyUserControl);
    //...
}

我收集了上面的解决方案(主要是@Idle_Mind中的第一个),我只是添加并调整了一些行;我将使用他的句子:


下面是上面评论中提到的事件方法的简单示例。

具有"后退"事件的用户控件:

No Change here

public partial class UserControl1 : UserControl
{
    public event dlgBack Back;
    private UserControl1 _previous = null;
    public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
    public UserControl1(UserControl1 previous)
    {
        InitializeComponent();
        this._previous = previous;
    }
    private void btnBack_Click(object sender, EventArgs e)
    {
        if (Back != null)
        {
            Back(this, _previous);
        }
    }
}

然后,窗体创建用户控件并订阅事件:

Let take a look at commented lines

public partial class Form1 : Form
{
    //prevUsr  is global instead
    private UserControl1 prevUsr = null;
    public Form1()
    {
        InitializeComponent();
    }
    private void btnAdd_Click(object sender, EventArgs e)
    {
        //prevUsr is removed from here
        //UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
        UserControl1 usr = new UserControl1(prevUsr);
        usr.Back += usr_Back;
        pnlUI.Controls.Clear();
        pnlUI.Controls.Add(usr);
        //prevUsr is updated
        prevUsr = usr;
    }
    void usr_Back(UserControl1 sender, UserControl1 previous)
    {
        pnlUI.Controls.Remove(sender);
        //prevUsr is updated
        prevUsr = previous;
        if (previous != null)
        {
            pnlUI.Controls.Add(previous);
        }
    }
}

并且,不要忘记设置单击用户控件的后退按钮btnBack_Click。

我希望这是有帮助的,它在我身边完美地工作;我可以发送或共享完整的VS项目(VS2012)。

我希望它对你有用,

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private int count = 0;
    private LinkedList<UserControl1> lstControls = new LinkedList<UserControl1>();
    private void btnAdd_Click(object sender, EventArgs e)
    {
        var c = new UserControl1();
        if (pnlUI.Controls.Count > 0)
        {
            lstControls.AddLast(pnlUI.Controls[0] as UserControl1);
            pnlUI.Controls.Clear();
        }
        c.lblTitle.Text = "Control #" + (++count).ToString();
        pnlUI.Controls.Add(c);
    }
    private void btnBack_Click(object sender, EventArgs e)
    {
        if (lstControls.Last != null)
        {
            var lastControl = lstControls.Last.Value;
            pnlUI.Controls.Clear();
            pnlUI.Controls.Add(lastControl);
            lstControls.RemoveLast();
        }
    }
}

我结合了idle_mind,rdavisau和fabrice的答案。我使用 rdavisau 代码在用户控件中取回 back 事件的控件和idle_mind,并为他在表单中的一些修改提供 fabrice。我希望我能把赏金分成三部分,所以我把它交给闲人。谢谢大家

我创建了一个类:

 class GetControls
{
    private Control[] cntrl;
    public Control[] Previous
    {
    get
    { 
        return cntrl;
    }
        set
        {
            cntrl = value;
        }
    }
}

在我的主表格上,这里是修订后的代码。

  GetControls help = new GetControls();
  private void btnpay_Click(object sender, EventArgs e)
    {

        TenderUI usr = new TenderUI(prevUsr);
        usr.Back += usr_Back;
        help.Previous = pnlUI.Controls.OfType<Control>().ToArray(); 
        pnlUI.Controls.Clear();
        pnlUI.Controls.Add(usr);

    }

并检索控件

 void usr_Back(TenderUI sender, TenderUI previous)
    {
        pnlUI.Controls.Remove(sender);
        if (help.Previous != null)
        {
            foreach (Control ctr in help.Previous)
            {
                pnlUI.Controls.Add(ctr);
            }
        }
    }