Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我需要从另一个类(C#)访问表单控件_C# - Fatal编程技术网

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

我需要从另一个类(C#)访问表单控件,c#,C#,在我的表单上,我有一个面板容器,名为“panelShowList” 在我的项目中,我添加了一个新类,如下所示: class myNewClass { private int newPanelPos = 30; private const int spaceBetweenElements = 30; private const int panelWidth = 90; private const int panelHeight = 40; private i

在我的表单上,我有一个面板容器,名为“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
        }
    }
}
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
        }
    }
基本上,我需要一种方法将ArrayList中的所有面板添加到表单中的“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
        }
    }
}
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();
另一种形式是开放的

如有任何建议,将不胜感激

另一种形式是开放的

这是因为您正在创建一个全新的表单:

frmMain f = new frmMain();
如果要修改现有表单的状态,则该代码将需要对该表单的引用。有很多方法可以做到这一点。可以简单地传递对该方法的引用:

public void displayPanels(frmMain myMainForm)
{
    foreach (Panel tmp in myPanels)
    {
        // myMainForm.panelShowList.Controls.Add(tmp);
        // etc.
    }
}
然后,当主窗体调用该方法时,它会提供对自身的引用:

instanceOfNewClass.displayPanels(this);
不过,老实说,现在还不清楚你想要什么样的结构。如果代码正在修改表单,那么我认为代码应该在表单上。它当然可以被组织成一个类,但也许那可以是一个这种形式的内部类,因为没有其他需要知道它

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


不过,这只是一个猜测,因为这里的对象结构不清楚。

可能有点晚,但无论如何,这里有另一种方法,它仍然比David的方法更清晰:

您应该在
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; }
}

表单只有在打开时才存在。所以,当它未打开时,不访问它是正常的。要修复它,您需要创建一个静态对象并将表单存储在其中。所以你可以在它关闭时访问它。@vgSefa:这本质上是使用静态值作为全局变量,这是一种非常糟糕的使用模式。保持值的范围比将它们转储到某个地方让所有人都看到要好。此外,您的第一个声明(“表单只有在打开时才存在”)显然是错误的。与任何对象一样,表单对象只要在作用域中就存在。请不要使用
ArrayList
。在这种情况下,最好使用通用列表:
private IList myPanels=new list()@khlr非常感谢您的建议。我没有任何C#方面的经验,所以我仍在学习很多。