我在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'
答案 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;
}
}