如何从窗体中的用户控件动态添加和删除用户控件
本文关键字:用户 控件 动态 删除 添加 窗体 | 更新日期: 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);
}
}
}