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

时间:2014-12-26 13:54:19

标签: 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
        }
    }
}

基本上,我需要一种方法来添加我的ArrayList中的所有面板" panelShowList"从我的形式控制。

我试过这样的事情:

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();

另一种形式是公开的。

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

  

另一个表单已打开

那是因为你正在创造一个全新的形式:

frmMain f = new frmMain();

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

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

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

instanceOfNewClass.displayPanels(this);

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

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

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

答案 1 :(得分:1)

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

您应该在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<Panel> _panels = new List<Panel>();

    public void AddPanel(Panel panel)
    {
        _panels.Add(panel);
    }

    public void DisplayPanels()
    {
        OnDisplayPanels(new DisplayPanelsEventArgs(_panels));
    }

    protected virtual void OnDisplayPanels(DisplayPanelsEventArgs e)
    {
        EventHandler<DisplayPanelsEventArgs> handler = DisplayPanelsInvoked;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public event EventHandler<DisplayPanelsEventArgs> DisplayPanelsInvoked;
}

internal class DisplayPanelsEventArgs : EventArgs
{
    public DisplayPanelsEventArgs(IList<Panel> panels)
    {
        Panels = panels;
    }

    public IList<Panel> Panels { get; private set; }
}

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

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

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<Panel> _panels = new List<Panel>();

    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<DisplayPanelsEventArgs> handler = PanelAdded;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    public event EventHandler<DisplayPanelsEventArgs> PanelAdded;
}

internal class DisplayPanelsEventArgs : EventArgs
{
    public DisplayPanelsEventArgs(IList<Panel> allPanels, Panel panelAddedLast)
    {
        AllPanels = allPanels;
        PanelAddedLast = panelAddedLast;
    }

    public IList<Panel> AllPanels { get; private set; }
    public Panel PanelAddedLast { get; private set; }
}