简体   繁体   English

Winform和用户控制-C#

[英]Winform & user control - C#

I have a Form and a UserControl. 我有一个窗体和一个UserControl。 The UserControl has a menu, and the form has a tabstrip (General, Food, Vitamins etc). UserControl有一个菜单,而窗体有一个Tabstrip(常规,食品,维生素等)。

In the UserControl, I have the following code: (Form name is frmForm, the tab names in the form are tabGeneral,tabFood, tabVitamins) 在UserControl中,我有以下代码:(表单名称为frmForm,表单中的选项卡名称为tabGeneral,tabFood,tabVitamins)

  frmForm fm=new frmForm();
  fm.tabMain.Selected=tabVitamins;

I call these line from the UserControl to capture the tab to get selected on the form, but it does not select the vitamins tab. 我从UserControl调用这些行以捕获要在表单上选择的选项卡,但是它没有选择“维生素”选项卡。

Where am I going wrong? 我要去哪里错了? I have access specifier as Protected Internal for tabs in the form. 我在表单中将访问标签指定为“受保护的内部”。

Please advice. 请指教。

Thanks, Karthick 谢谢,卡西克

When you write new frmForm() , you're creating a completely new instance of frmForm , which is then discarded. 编写new frmForm() ,您将创建一个全新frmForm实例,然后将其丢弃。

To get the frmForm instance that holds your control, call the FindForm() method and cast to frmForm . 要获取保存您的控件的frmForm实例,请调用FindForm()方法并将其frmFormfrmForm

For example: 例如:

frmForm myForm = FindForm() as frmForm; 
if(myForm != null)
    myForm.tabMain.SelectedTab = myForm.tabVitamins;

If the control is on some other form, this code won't do anything. 如果控件采用其他形式,则此代码将不执行任何操作。


By the way, Hungarian notation is frowned upon in .Net. 顺便说一下,.Net不支持匈牙利符号。
Your form should probably be named something like MainForm . 您的表单应该命名为MainForm

SLaks has correctly pointed out your fundamental error, and given you a valid example of a way, via a call to the method 'FindForm, to get the Form the UserControl is sited on. SLaks已经正确指出了您的基本错误,并通过调用方法'FindForm,给出了一种有效的方法示例,该方法用于获取用户控件所在的表单。

It may be valuable to you to keep in mind that a UserControl (and all Controls) also has a 'Parent property, but, of course, a UserControl could be placed inside another Control on a Form (like your UserControl could be inside a Panel on the Form) : in that case the UserControl's Parent would be the control it's inside on the Form (like, a Panel), not the Form itself, but 'FindForm will do the right thing to get you the Form it's on. 对您而言,记住一个UserControl(和所有Controls)也具有'Parent属性可能是有价值的,但是,当然,一个UserControl可以放置在窗体上的另一个Control内(例如您的UserControl可以在Panel内)在窗体上):在这种情况下,UserControl的父控件将是它在窗体(如面板)中的控件,而不是窗体本身,但是'FindForm将做正确的事来获取您所在的窗体。

However you are calling a Method every time you use 'FindForm, and "best practice" suggests that what you want to do is to "inject" a reference to the Form into the UserControl at run-time so that it can always access its Form property easily, without calling a 'Method. 但是,每次使用'FindForm时,您都在调用Method,并且“最佳实践”建议您要做的是在运行时将对Form的引用“注入”到UserControl中,以便它始终可以访问其Form。属性,而无需调用“方法”。

In your example, on a practical level, this (calling the Method) may make almost no difference in performance, but, imho, as you get to a place with WinForms and .NET where you might have a UserControl that will need access to its Parent Form very frequently, this will pay off, and it's a better way to structure your code in the long run, for maintenance. 在你的榜样,在实践层面上,这(调用方法)可能使在性能上几乎没有差别,但是,恕我直言,当你到一个地方与WinForms和.NET,你可能有一个用户控件, 需要访问它的Parent Form非常频繁,这会有所回报,从长远来看,这是一种更好的结构化代码以进行维护的更好方法。

Wes showed you one way you can "embed" (inject) the UserControl's hosting Form : using an overloaded constructor for the UserControl. Wes向您展示了一种“嵌入”(注入)UserControl宿主窗体的方式:使用UserControl的重载构造函数。 But that requires you to modify the Designer.cs file in standard WinForms, and I strongly advise you against that, even though it will work. 但这需要您在标准WinForms中修改Designer.cs文件,我强烈建议您这样做,即使它可以工作。 Particularly if you are just "getting your feet on the ground" in .NET, I strongly advise you against modifying it, or anything having to do with the Form's constructor and its internal call to : InitializeComponent(); 特别是如果您只是在.NET中“站稳脚跟”,我强烈建议您不要修改它,或者与Form的构造函数及其对内部的调用有关的任何事情:InitializeComponent();

Also, as you progress with WinForms you are going to meet many situations where you are going to want instances of "objects" (a Control, a Form, an instance of a Class) to contain references to other instances of "objects. 此外,随着WinForms的发展,您将遇到很多情况,其中您希望“对象”的实例(控件,窗体,类的实例)包含对“对象”的其他实例的引用。

If you can understand and use one simple use of "injection" here, you are going to make progress to make yourself ready to handle more complex .Net programming in the future. 如果您能在这里理解和使用“注入”的一种简单用法,那么您将取得进展,使自己准备在将来处理更复杂的.Net编程。

Another way is to put a Public Property in the UserControl that can be set in code from the MainForm. 另一种方法是将公共属性放在UserControl中,该属性可以在MainForm中的代码中进行设置。 In the UserControl something like : 在UserControl中类似:

private frmForm ParentForm;

public frmForm UCParentForm
{
    set { ParentForm = value; }
}

So then in your main form's code, perhaps in the Load event like this : 因此,在您的主窗体代码中,也许在Load事件中,如下所示:

private void frmForm_Load(object sender, EventArgs e)
{
    TheUserControl.UCParentForm = this;
}

or when you need to, you set the UserControl's 'ParentForm property once. 或者在需要时,一次设置UserControl的'ParentForm属性。 So you have eliminated using the method 'FindForm(). 因此,您无需使用方法'FindForm()。

In this case, if you only want access to a specific control on the UserControl's Parent Form, like a TabControl, you might consider that you want to make the Property you set of type TabControl, rather than Form : the same coding technique shown above can be used in the UserControl : 在这种情况下,如果只希望访问UserControl的父窗体上的特定控件(如TabControl),则可能会认为您希望将所设置的属性设置为TabControl类型,而不是Form类型:上面显示的相同编码技术可以在UserControl中使用:

private TabControl mainFormTabControl;

public TabControl MainFormTabControl
{
    set { mainFormTabControl = value; }
}

imho, it is when you are creating UserControls dynamically at run-time, using an overloaded constructor, as Wes suggests, is the best strategy. 恕我直言,这是您在运行时动态创建UserControl时的最佳策略,正如Wes建议的那样,使用重载的构造函数。 And using overloaded constructors has many, many others uses in .NET that you'll get into. 使用重载的构造函数在.NET中有很多很多其他用途,您会发现。

good luck ! 祝好运 !

You should not be creating a new frmForm() inside the user control. 您不应在用户控件内创建新的frmForm()。 You could pass a reference to the frmForm to the user control. 您可以将对frmForm的引用传递给用户控件。

In your user control constructor try something like this. 在您的用户控件构造函数中,尝试执行以下操作。

private frmForm fm;

public YourUserControl(frmForm fm)
{
    this.fm = fm;
}

Then you could use. 然后,您可以使用。

fm.tabMain.Selected=tabVitamins;

Does that help? 有帮助吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM