我需要从另一个类(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
实现需要按特定顺序调用方法。 对象上的任何给定操作都应完全封装逻辑以完成该操作。 如果对象在该逻辑完成之前不处于有效状态,则一些初始化逻辑可以属于构造函数。
这有点猜想,因为这里的对象结构并不清楚。