如何从静态方法访问控件?

时间:2009-06-04 17:37:01

标签: c# .net winforms

我在C#.NET中有一个应用程序,它有一个MainForm和几个类。

其中一个类接收来自网络的传入数据消息。我需要将这些消息的文本附加到MainForm上的多行文本框中。

我可以通过使方法静态将消息发送到MainForm中的方法,但静态方法无法访问MainForm的控件。

TheIncomingDataClass.cs

namespace TheApplicationName
{
     class TheIncomingDataClass
     {

     public void IncomingMessage(IncomingMessageType message)
     {
          TheApplicationName.MainForm.ReceiveMSG(message);
     }

MainForm.cs

public static void ReceiveMSG(string message)
{
     txtDisplayMessages.AppendText(message); //This line causes compile error
}

编译错误:

  

非静态字段,方法或的对象引用是必需的   property'TheApplicationName.MainForm.txtDisplayMessages'

10 个答案:

答案 0 :(得分:9)

静态方法无权访问txtDisplayMessages等成员,因为它不是该实例的一部分。我建议你做一些关于静态方法和诸如此类的概念的阅读,因为这是一个相当语言不可知的概念。最好通过删除静态修饰符来实现该方法,因为它不需要是静态的 - 它似乎需要由该对象的特定实例调用。

答案 1 :(得分:7)

要继续你的方式,你的“TheIncomingDataClass”应该引用它应该与之对接的MainForm对象。当您创建此类的实例(可能来自MainForm的实例方法)时,您需要传入对此MainForm对象的引用。

class TheIncomingDataClass{
    MainForm form;

    public TheIncomingDataClass(MainForm form){
        this.form = form;
    }
}

class MainForm : Form{
    MainForm(){
        new TheIncomingDataClass(this);
    }
}

但是,正如Bugs所建议的那样,您可能最好将此活动设为TheIncomingDataClass并从MainForm订阅。

class IncomingMessageEventArgs : EventArgs{
    IncomingMessageType message;

    public IncomingMessageType Message{get{return message;}}

    public IncomingMessageEventArgs(IncomingMessageType message){
        this.message = message;
    }
}

class TheIncomingDataClass{
    public event EventHandler<IncomingMessageEventArgs> MessageReceived;

    protected virtual void OnMessageReceived(IncomingMessageEventArgs e){
        if(MessageReceived != null)
            MessageReceived(this, e);
    }

    public void IncomingMessage(IncomingMessageType message){
        OnMessageReceived(new IncomingMessageEventArgs(message));
    }
}

class MainForm : Form{
    MainForm(){
        new TheIncomingDataClass().MessageReceived +=
            (s, e)=>txtDisplayMessages.AppendText(e.Message.ToString());
    }
}

答案 2 :(得分:4)

可以传递对当前表单的引用,如下所示:

public static void ReceiveMSG(string message, MainForm mainform)
{
     mainform.txtDisplayMessages.AppendText(message); 
}

虽然建议事件可能是一种更好的方法。

答案 3 :(得分:3)

从表中可以订阅的类中引发一个事件。

答案 4 :(得分:1)

只需删除静态修改器,您就不需要它。了解静态here

答案 5 :(得分:1)

您可以通过删除static关键字来解决此问题。

当你看到“静态”时,请想一想:没有这种类型的实例。

调用非静态方法时,必须显式使用某个实例。该方法可以使用“this”关键字访问该实例。

当您调用静态方法时,没有实例 - 您已经放弃了OO的边界,现在处于结构或函数编程上下文中。如果你想要某个实例,你需要把它作为一个参数。

答案 6 :(得分:1)

我认为你可能会对此采取错误的做法。听起来您正试图从外部进程将消息推送到客户端。有办法做到这一点,但它会变得复杂。我的建议是让客户端定期查询任何进程有数据 - 可能每10秒钟根据您的需要进行一次。这比从服务器推送到客户端要容易得多。

答案 7 :(得分:1)

好的,这里。 静态方法只能访问静态成员。您的ReceiveMSG方法是静态的。 txtDisplayMessages不是,因此您无法访问它。 为什么你的方法需要是静态的?毋庸置疑,如果您删除将解决问题的静态关键字。

只需将ReceiveMSG作为类的一部分,创建该类的实例,然后在该实例上调用该方法。

我认为您应该发布您期望的解决方案。

答案 8 :(得分:0)

看到你是C#的新手,我会尽可能简单地保持这个。你应该有一个Program.cs文件,它有一个方法Main(这可能是由Visual Studio生成的)。您需要使其如下所示:

class Program
{
    public static readonly MainForm MainForm;

    static void Main()
    {
        Application.EnableVisualStyles();
        MainForm = new MainForm(); // These two lines
        Application.Run(MainForm); // are the important ones.
    }
}

现在,在您收到的消息中,您将有办法访问该表单。

 public void IncomingMessage(IncomingMessageType message)
 {
      Program.MainForm.RecieveMSG(message);
 }

表单中的那个方法将是一个实例(非静态)方法。 E.g。

 public void RecieveMSG(IncomingMessageType message) // NB: No static
 {
     txtDisplayMessages.Text = message.Text; // Or whatever.
 }

有更好的方法可以做到 - 但作为初学者,我认为这将是最好的方法。

静态和实例之间的区别(实例是当你不说静态时)是巨大的。要获取实例方法,字段或属性(在C#中统称为成员),您需要拥有包含实例。所以:

 Person p = new Person(); // You now have an instance.
 p.Name = "Fred"; // You are using an instance property.

静态是相反的,它们在你的应用程序的任何地方都是一样的(技术上更像是在同一个AppDomain中 - 但如果你是初学者,你不需要担心这一段时间)。您不需要实例来获取它们(对代码片段的支持“静态方法只能访问静态成员”)。例如:

 // Where Planet is a class and People is a static property.
 // Somewhat confusingly the Add method is an instance - best left for the student :).
 Planet.People.Add(new Person("Fred")); 

希望这可以很好地指示静态和实例是什么以及在何处使用它们。最重要的是尽量避免静态成员 - 他们可能会导致维护噩梦。

微软对此有重要概念write-up

答案 9 :(得分:0)

private void FormMain_Load(object sender, EventArgs e)
{
    TheIncomingDataClass.SetupControl(textBox1);
}

public class TheIncomingDataClass
{
    public static TextBox textbox = new TextBox();
    public static void SetupControl(TextBox txt)
    {
        textbox = txt;
    }
    public void IncomingMessage(string message)
    {
        textbox.Text = message;
    }
}