我有一个Form和一个UserControl。 UserControl有一个菜单,表格有一个标签(一般,食物,维生素等)。
在UserControl中,我有以下代码:(表单名称为frmForm,表单中的选项卡名称为tabGeneral,tabFood,tabVitamins)
frmForm fm=new frmForm();
fm.tabMain.Selected=tabVitamins;
我从UserControl调用这些行来捕获选项卡以在表单上选中,但它不会选择维生素选项卡。
我哪里错了?对于表单中的选项卡,我有访问说明符作为Protected Internal。
请建议。
谢谢, Karthick
答案 0 :(得分:7)
当您编写new frmForm()
时,您正在创建一个全新的 frmForm
实例,然后将其丢弃。
要获取包含您控件的frmForm
实例,请调用FindForm()
方法并转换为frmForm
。
例如:
frmForm myForm = FindForm() as frmForm;
if(myForm != null)
myForm.tabMain.SelectedTab = myForm.tabVitamins;
如果控件是其他形式,则此代码不会执行任何操作。
顺便说一句,匈牙利的符号在.Net中不受欢迎
您的表单应该命名为MainForm
。
答案 1 :(得分:3)
SLaks正确地指出了你的基本错误,并通过调用方法'FindForm来获得一个有效的方法示例,以获取位于UserControl的表单。
记住UserControl(和所有控件)也有'父属性',但是,当然,UserControl可以放在窗体上的另一个控件中(比如你的UserControl可能是在Form上的Panel中):在这种情况下,UserControl的Parent将是它在Form上的控件(比如Panel),而不是Form本身,但'FindForm会做正确的事情来获取它所在的Form
但是每次使用'FindForm时都会调用一个方法,而“最佳实践”表明你想要做的是在运行时将一个对Form的引用“注入”UserControl,这样它就可以无需调用“方法”即可轻松访问其Form属性。
在你的例子中,在实际的层面上,这个(调用Method)可能在性能上几乎没有差别,但是,当你到达一个WinForms和.NET的地方你可能有一个UserControl 需要非常频繁地访问其父表单,这将获得回报,而且从长远来看,这是构建代码以进行维护的更好方法。
Wes向您展示了一种可以“嵌入”(注入)UserControl的托管表单的方法:使用UserControl的重载构造函数。但是这需要你修改标准WinForms中的Designer.cs文件,我强烈建议你不要这样做,即使它会起作用。特别是如果您只是在.NET中“站稳脚跟”,我强烈建议您不要修改它,或者与Form的构造函数及其内部调用有关的任何内容:InitializeComponent();
此外,随着WinForms的发展,您将遇到许多情况,您希望“对象”实例(Control,Form,Class的实例)包含对“对象”的其他实例的引用
如果你能理解并在这里使用一个简单的“注入”,那么你将在未来做好准备,为将来处理更复杂的.Net编程做好准备。
另一种方法是在UserControl中放置一个Public Property,可以在MainForm的代码中设置。在UserControl中,例如:
private frmForm ParentForm;
public frmForm UCParentForm
{
set { ParentForm = value; }
}
然后在你的主窗体的代码中,也许在这样的Load事件中:
private void frmForm_Load(object sender, EventArgs e)
{
TheUserControl.UCParentForm = this;
}
或者在需要时,将UserControl的'ParentForm属性设置一次。所以你已经消除了使用方法'FindForm()。
在这种情况下,如果你只想访问UserControl的父窗体上的特定控件,比如TabControl,你可能会认为你想要设置你设置的属性TabControl,而不是Form:相同的编码技术如上所示可以在UserControl中使用:
private TabControl mainFormTabControl;
public TabControl MainFormTabControl
{
set { mainFormTabControl = value; }
}
imho,当你在运行时动态创建UserControl时,使用重载的构造函数,正如Wes所说,是最好的策略。使用重载的构造函数有很多很多其他用于.NET的东西。
祝你好运!
答案 2 :(得分:1)
您不应该在用户控件中创建新的frmForm()。您可以将对frmForm的引用传递给用户控件。
在你的用户控件构造函数中尝试这样的事情。
private frmForm fm;
public YourUserControl(frmForm fm)
{
this.fm = fm;
}
然后你可以使用。
fm.tabMain.Selected=tabVitamins;
这有帮助吗?