Как получить доступ к элементу управления из статического метода? - PullRequest
6 голосов
/ 04 июня 2009

У меня есть приложение на 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
}

Ошибка компиляции:

Ссылка на объект требуется для нестатического поля, метода или свойство 'TheApplicationName.MainForm.txtDisplayMessages'

Ответы [ 10 ]

9 голосов
/ 04 июня 2009

Статический метод не имеет доступа к таким элементам, как txtDisplayMessages, поскольку он не является частью этого экземпляра. Я предлагаю вам немного почитать концепции статических методов и еще много чего, потому что это довольно независимое от языка понятие. Этот метод лучше всего обслуживать, удаляя статический модификатор, потому что он не должен быть статическим - похоже, его должен вызывать именно этот экземпляр этого объекта.

7 голосов
/ 04 июня 2009

Чтобы продолжить, как вы это делаете, ваш "TheIncomingDataClass" должен иметь ссылку на объект MainForm, с которым он должен взаимодействовать. Когда вы создаете экземпляр этого класса (предположительно из метода экземпляра MainForm), вам нужно будет передать ссылку на этот MainForm объект.

class TheIncomingDataClass{
    MainForm form;

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

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

Однако, как подсказывают Ошибки , вам, вероятно, лучше сделать это событие на 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());
    }
}
4 голосов
/ 04 июня 2009

Можно передать ссылку на текущую форму следующим образом:

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

Хотя, как предполагалось, событие, вероятно, является лучшим способом сделать это.

3 голосов
/ 04 июня 2009

вызвать событие из класса, на который форма может подписаться.

1 голос
/ 04 июня 2009

Хорошо, здесь идет. Статические методы могут получить доступ только к статическим членам. Ваш метод ReceiveMSG является статическим. txtDisplayMessages нет и, следовательно, вы не можете получить к нему доступ. Почему ваш метод должен быть статичным? Само собой разумеется, если вы удалите статическое ключевое слово, которое решит вашу проблему.

Просто сделайте ReceiveMSG частью класса, создайте экземпляр класса и затем вызовите метод для этого экземпляра.

Я думаю, вы должны опубликовать решение, которое вы ожидаете.

1 голос
/ 04 июня 2009

Я думаю, вы могли бы ошибиться в этом. Похоже, вы пытаетесь отправить сообщения клиенту от внешнего процесса. Есть способы сделать это, но это будет сложно. Я бы посоветовал клиенту периодически опрашивать любой процесс, в котором есть данные - возможно, каждые 10 секунд, в зависимости от ваших потребностей. Это будет намного проще, чем переход с сервера на клиент.

1 голос
/ 04 июня 2009

Вы можете решить эту проблему, удалив ключевое слово static.

Когда вы видите «статический», подумайте: без экземпляра этого типа.

Когда вы вызываете нестатический метод, вы должны явно использовать некоторый экземпляр. Метод может получить доступ к этому экземпляру с помощью ключевого слова this.

Когда вы вызываете статический метод, его нет - вы отказались от границ ОО и теперь находитесь в контексте структурного или функционального программирования. Если вам нужен экземпляр чего-либо, вам нужно ввести его в качестве параметра.

1 голос
/ 04 июня 2009

Просто удалите статический модификатор, он вам не нужен для ваших целей. Читайте о статике здесь .

0 голосов
/ 31 июля 2018
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;
    }
}
0 голосов
/ 04 июня 2009

Учитывая, что вы новичок в 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);
 }

Тогда этот метод в форме будет экземпляром (не статическим). Э.Г.

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

Есть лучшие способы сделать это, но я думаю, что для новичка это будет лучшим подходом.

Разница между static и instance (например, когда вы не говорите static) огромна. Чтобы получить доступ к методу, полю или свойству экземпляра (которые все вместе называются членами в 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")); 

Надеюсь, это даст вам хорошее представление о том, что такое static и instance, и где их использовать. Однако самое главное - стараться избегать статических элементов как можно лучше - они могут вызвать кошмары при обслуживании.

У Microsoft есть целая статья о важных концепциях, касающихся этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...