我需要从另一个类(C#)访问一个表单控件

在我的表单上,我有一个Panel容器,名为“panelShowList”。

在我的项目中,我添加了一个新类,如下所示:

class myNewClass { private int newPanelPos = 30; private const int spaceBetweenElements = 30; private const int panelWidth = 90; private const int panelHeight = 40; private int elementPos = 0; private ArrayList myPanels = new ArrayList() { }; // some irelevant methods public void addElementPanels(Panel dataPanel, Panel nextPanel) { myPanels.Add(dataPanel); myPanels.Add(nextPanel); } public void displayPanels() { foreach (Panel tmp in myPanels) { // here i'm stuck // i need to do something like this : // myMainForm.panelShowList.Controls.Add(tmp); // of course this is wrong! but i need a method to acces that control } } } 

基本上,我需要一种方法从我的表单中的“panelShowList”控件上添加我的ArrayList中的所有面板。

我试过这样的事情:

 public void displayPanels() { frmMain f = new frmMain(); foreach (Panel tmp in myPanels) { f.display(tmp); // where display(Panel tmp) is a function in my Form, who access // "panelShowList" control and add a new Panel } } 

但它只有在我这样做时才有效:

 f.ShowDialog(); 

另一种forms是公开的。

任何建议将不胜感激。

也许有点晚了,但无论如何,这是另一种方法,它比大卫的方法更干净:

您应该在MyNewClass添加一个EventHandler。 然后,您可以在表单中订阅该事件。

 public partial class Form1 : Form { private readonly MyNewClass _myNewClass; public Form1() { InitializeComponent(); _myNewClass = new MyNewClass(); _myNewClass.DisplayPanelsInvoked += DisplayPanelsInvoked; } private void DisplayPanelsInvoked(object sender, DisplayPanelsEventArgs e) { var panels = e.Panels; // Add the panels somewhere on the UI ;) } } internal class MyNewClass { private IList _panels = new List(); public void AddPanel(Panel panel) { _panels.Add(panel); } public void DisplayPanels() { OnDisplayPanels(new DisplayPanelsEventArgs(_panels)); } protected virtual void OnDisplayPanels(DisplayPanelsEventArgs e) { EventHandler handler = DisplayPanelsInvoked; if (handler != null) { handler(this, e); } } public event EventHandler DisplayPanelsInvoked; } internal class DisplayPanelsEventArgs : EventArgs { public DisplayPanelsEventArgs(IList panels) { Panels = panels; } public IList Panels { get; private set; } } 

在我看来,这是一个更好的解决方案,因为您不需要向MyNewClass实例提供表单的引用。 所以这种方法减少了耦合,因为只有表单对MyNewClass有依赖性。

如果您总是希望在添加面板时“更新”表单,则可以删除DisplayPanels -method并将代码缩短为:

 public partial class Form1 : Form { private readonly MyNewClass _myNewClass; public Form1() { InitializeComponent(); _myNewClass = new MyNewClass(); _myNewClass.PanelAdded += PanelAdded; } private void PanelAdded(object sender, DisplayPanelsEventArgs e) { var panels = e.AllPanels; // Add the panels somewhere on the UI ;) } } internal class MyNewClass { private IList _panels = new List(); public void AddPanel(Panel panel) { _panels.Add(panel); OnPanelAdded(new DisplayPanelsEventArgs(_panels, panel)); // raise event, everytime a panel is added } protected virtual void OnPanelAdded(DisplayPanelsEventArgs e) { EventHandler handler = PanelAdded; if (handler != null) { handler(this, e); } } public event EventHandler PanelAdded; } internal class DisplayPanelsEventArgs : EventArgs { public DisplayPanelsEventArgs(IList allPanels, Panel panelAddedLast) { AllPanels = allPanels; PanelAddedLast = panelAddedLast; } public IList AllPanels { get; private set; } public Panel PanelAddedLast { get; private set; } } 

另一种forms是公开的

那是因为你正在创建一个全新的forms:

 frmMain f = new frmMain(); 

如果要修改现有表单的状态,该代码将需要对该表单的引用。 有很多方法可以做到这一点。 一种可能是简单地传递对该方法的引用:

 public void displayPanels(frmMain myMainForm) { foreach (Panel tmp in myPanels) { // myMainForm.panelShowList.Controls.Add(tmp); // etc. } } 

然后,当您的主窗体调用该方法时,它会提供对自身的引用:

 instanceOfNewClass.displayPanels(this); 

虽然,老实说,你在这里找到什么样的结构还不是很清楚。 如果代码正在修改表单,那么我想代码应该在该表单上 。 它当然可以被组织成一个类,但也许它可以是该forms的内部类,因为没有其他东西需要知道它。

我还担心你的myNewClass实现需要按特定顺序调用方法。 对象上的任何给定操作都应完全封装逻辑以完成该操作。 如果对象在该逻辑完成之前不处于有效状态,则一些初始化逻辑可以属于构造函数。

这有点猜想,因为这里的对象结构并不清楚。