在 C# 中动态创建的用户控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/578954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamically Created User Controls In C#
提问by THE DOCTOR
I am working in a C# winforms project and I have a user control which gets loaded upon its selection from a tool-strip menu. I have a dictionary lookup set to occur upon form load of the user control for other functionality. Also, when I close the user control I am just using the ".Hide();" method. I noticed that when I load the user control the first time everything is fine, but when I close it and choose to open it again the 2nd time it creates a new instance of the object thus throwing off my dictionary lookup. Therefore, I wrote some code in an attempt to fix the issue.
我在一个 C# winforms 项目中工作,我有一个用户控件,它在从工具条菜单中选择时加载。我有一个字典查找设置为其他功能的用户控件的表单加载时发生。另外,当我关闭用户控件时,我只是在使用“.Hide();” 方法。我注意到当我第一次加载用户控件时一切正常,但是当我关闭它并第二次选择再次打开它时,它会创建对象的一个新实例,从而放弃我的字典查找。因此,我写了一些代码试图解决这个问题。
What I need to do is to somehow say that if an instance of the user control already exists, do not create a new instance of that object. Instead, just make the user control visible again. Therefore I have written code in an attempt to accomplish this purpose. When I select the item the first time, everything is fine. When I hide the user control and try to re-open it again nothing happens.
我需要做的是以某种方式说如果用户控件的实例已经存在,则不要创建该对象的新实例。相反,只需使用户控件再次可见。因此,我编写了代码以尝试实现此目的。当我第一次选择该项目时,一切都很好。当我隐藏用户控件并尝试再次重新打开它时,没有任何反应。
The following is the code I have written for this purpose which occurs upon the selection of the item from the tool-strip menu:
以下是我为此目的编写的代码,它发生在从工具条菜单中选择项目时:
if (Controls.ContainsKey("CheckAvailUserControl"))
{
Controls["CheckAvailUserControl"].Dock = DockStyle.Fill;
Controls["CheckAvailUserControl"].Visible = true;
Controls["CheckAvailUserControl"].Show();
Controls["CheckAvailUserControl"].Refresh();
}
else
{
UserControl checkAvailUserControlLoad = new CheckAvailUserControl();
Controls.Add(checkAvailUserControlLoad);
checkAvailUserControlLoad.Dock = DockStyle.Fill;
checkAvailUserControlLoad.Visible = true;
checkAvailUserControlLoad.Show();
}
When I trace through my code in the debugger it is in fact hitting the right parts of the above if/else statement. Its just not displaying the user control on the screen the 2nd time I attempt to load it.
当我在调试器中跟踪我的代码时,它实际上击中了上述 if/else 语句的正确部分。它只是在我第二次尝试加载它时没有在屏幕上显示用户控件。
The question is: How do I get the user control to load correctly after I close it, then select it from the tool-strip menu again?
问题是:如何在关闭用户控件后正确加载它,然后再次从工具条菜单中选择它?
采纳答案by Daniel LeCheminant
I think that Controls.ContainsKey(...) is always returning false, because you never assigned a name to your control when you created it.
我认为 Controls.ContainsKey(...) 总是返回 false,因为您在创建控件时从未为其分配名称。
If, when you create the control, you say
如果,当您创建控件时,您说
//...
checkAvailUserControlLoad.Name = "Something"
//...
Controls.Add(checkAvailUserControlLoad);
then
然后
Controls.ContainsKey("Something")
will return true, and you'll be able to re-use the control by using Controls["Something"]
将返回true,您将能够通过使用重新使用控件 Controls["Something"]
回答by Joel Coehoorn
This could work, but I think it's a little bit backwards: you're throwing new code at a problem that could be solved instead by moving your old code.
这可以工作,但我认为它有点倒退:您将新代码投入到可以通过移动旧代码解决的问题上。
Instead, think about how the events work in your form. I bet that if you move your creating code to a slightly different event, or detect when the event is fired later and ignore those, you could fix the problem in a much nicer way.
相反,请考虑事件在您的表单中是如何工作的。我敢打赌,如果您将创建代码移动到稍微不同的事件中,或者稍后检测到事件何时触发并忽略它们,那么您可以以更好的方式解决问题。
回答by Jerry Nixon
Here you go:
干得好:
private void button_Click(object sender, EventArgs e)
{
// pass in the containing panel
LoadControl<MyControls.MyControl>(panelContainer);
}
void LoadControl<T>(Panel panel) where T : Control, new()
{
T _Control = GetControl<T>(panel);
if (_Control == null)
{
_Control = new T();
_Control.Dock = DockStyle.Fill;
panel.Controls.Add(_Control);
}
_Control.BringToFront();
}
T GetControl<T>(Panel panel) where T : Control
{
Type _Type = typeof(T);
String _Name = _Type.ToString();
if (!panel.Controls.ContainsKey(_Name))
return null;
T _Control = panel.Controls[_Name] as T;
return _Control;
}