2009-06-04 27 views
6

私はメインフォームといくつかのクラスを持つC#.netのアプリケーションを持っています。
これらのクラスの1つは、ネットワークから着信データメッセージを受信します。
これらのメッセージのテキストを、MainFormの複数行のテキストボックスに追加する必要があります。
メソッドを静的にすることによってMainFormのメソッドにメッセージを送信できますが、静的メソッドはMainFormのコントロールにアクセスできません。C#.NETでは、静的メソッドからコントロールにアクセスするにはどうすればよいですか?

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 '

何か助けていただければ幸いです。

私はまだかなりのC#初心者ですので、説明してください。

答えて

9

静的メソッドは、そのインスタンスの一部ではないため、txtDisplayMessagesなどのメンバーにはアクセスできません。静的メソッドやその他のものの概念については、かなり言語にとらわれない概念なので、読んでみることをお勧めします。静的である必要はないので、静的修飾子を削除すると、このメソッドは最も効果的です。つまり、そのオブジェクトの特定のインスタンスによって呼び出される必要があるようです。

+0

メソッドからstaticキーワードを削除すると、もはやIncomingDataクラスから呼び出すことができなくなります。私はあなたが「そのオブジェクトのその特定のインスタンスによって呼び出される」ということを理解していません。さらに説明できますか?私はこれらのメッセージを受け取ったら直ちにテキストボックスに送信する必要があることを覚えておいてください。イベントはメッセージの受信になります。ありがとう。 – timmyg

+0

MainFormで呼び出すのは静的なので、私は推測します。 ReceiveMSG()[または単にReceiveMSG()]。 Instanceを作成するには、MainFormの特定のインスタンス(MainForm mf = new MainForm()など)から呼び出す必要があります。その後、それをmfと呼ぶことができます。 ReceiveMSG()、mfをMainFormのインスタンスに名前を付けたものに置き換えます。違反はありませんが、オブジェクト指向に関するいくつかの言語に依存しない文献を読んでから、これが何を意味しているのかを学び、C#の構文がどのように関係しているかを見ておく必要があります。 – Annath

+0

真剣に、あなたはC#経由でCLRをつかむべきです。それは簡単に読むことができます(第1章をスキップしてください)。 – Will

3

フォームを購読できるクラスからイベントを発生させます。

1

スタティックモディファイアを削除するだけで、目的に合わせて使用​​する必要はありません。統計情報hereについて読む

4

このような現在のフォームへの参照を渡すために、その可能性:

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

などのイベントは、おそらくそれを行うための良い方法である提案が。

+0

これは私にとっては役に立ちません。私は 'ReceiveMSG'を別のクラスの中に入れました。' MainForm mainform'がパラメータとして宣言されていても、コントロールにはアクセスできません。 – ellekaie

1

この問題を解決するには、staticキーワードを削除します。

「静的」が表示されたら、次のように考える:このタイプのインスタンスなし。

非静的メソッドを呼び出すときは、明示的にインスタンスを使用する必要があります。このメソッドは "this"キーワードを使用してそのインスタンスにアクセスできます。

静的メソッドを呼び出すと、インスタンスは存在しません。つまり、オブジェクト指向の境界を破棄し、構造または関数プログラミングのコンテキストになりました。あなたが何かのインスタンスを望むなら、それをパラメータとして持ち込む必要があります。

1

私はあなたがこれについて間違ったアプローチを取っているかもしれないと思います。外部プロセスからクライアントにメッセージをプッシュしようとしているようです。これを行う方法はありますが、複雑になるでしょう。私の提案は、どのプロセスにもデータが定期的にポーリングされるようにすることです。必要に応じて10秒ごとに設定してください。これは、サーバーからクライアントへのプッシュよりもはるかに簡単です。

+0

ジョナサン - リモーティングを使用しているとポーリングが悪化するのはなぜですか?スレッディングに関しては、どのようなアプローチが示唆されているのかよく分かりませんが、以下の提案のほとんどはイベントを含むようです。イベントを使用する場合、同じスレッド問題が発生します。 彼は初心者だと言っていますので、ここでタイマーを叩いて、x秒ごとに新しいメッセージをチェックするという、最も簡単な方法を提案しています。あなたがuiを更新しようとしている場合は、invokeを呼び出します。イベントルートに行く場合、同じことをしなければなりません。 – Rob

+0

-Um、いいえ、タイマーは別のスレッドで実行されます。 - 同じマシン上のデータソースであると仮定していますが、作成者はこれを決して定義しませんでした。彼は単にソースが「ネットワークからの着信データメッセージ」だと言っていましたが、これはいろいろなことができますが、少なくともソースは同じappdomainにないことを意味します。著者は経験が限られていて、複数のプロセスとのやりとりで対処していることを考えると、リモートイベントをどのように消費するのか理解していると思いますか?彼が考えなかった可能性のある選択肢を放棄しようとするのは簡単なことです。 – Rob

+0

私は訂正し、私は他のコメントを引っ込めました。私は彼のネットワークコードが同じAppDomainにあると仮定しました。いずれにしても:: "このWindowsタイマーはシングルスレッド環境用に設計されています[...]"彼のUIはブロックされます。 のテストはさらに簡単です。 –

5

あなたのやり方をやり直すには、 "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()); 
    } 
} 
+0

私はあなたのメソッドを使用しようとしていて、すべてがメインフォームの最後の部分を除いてうまくいっています。 "(s、e)=> txtDisplayMessages.AppendText(e.Message.ToString());"このコード行は、多くのコンパイルエラーを返します。特に(s、e)部分。 – timmyg

1

ここに行きます。 静的メソッドは静的メンバーにのみアクセスできます。 ReceiveMSGメソッドは静的です。 txtDisplayMessagesはそうではないため、アクセスできません。 メソッドが静的である必要があるのはなぜですか?言うまでもなく、問題を解決する静的キーワードを削除した場合。

クラスのReceiveMSGの一部を作成し、そのクラスのインスタンスを作成してインスタンス上でメソッドを呼び出します。

私はあなたが期待している解決策を投稿するべきだと思います。

0

C#を初めてご使用の方には、できるだけシンプルにしておきます。 Program.csファイルには、Mainメソッドが1つあります(これは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. 
} 

これを行うにはより良い方法がありますが、初心者としてはこれが最善のアプローチだと思います。

静的とインスタンス(インスタンスは静的とは言わない)の違いは大きいです。インスタンスメソッド、フィールド、またはプロパティ(C#でまとめてメンバと呼ばれる)に到達するには、そのインスタンスを持つ必要があります。だから、:

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

静的が反対している、彼らはあなたのアプリケーション内のどこにでも同じです(もっと技術的に同じアプリケーションドメイン内で - しかし、あなたはしばらくの間、それを心配する必要はありません初心者であれば)。それらに到達するためのインスタンスは必要ありません(コード・ウィジェット「静的メソッドは静的メンバーにのみアクセスできます」)。例:

// 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を持っています。

+0

静的メンバーはメンテナンスの悪夢をどのように作りますか? – Rob

+0

リファクタリングが難しくなります。時間と時間をもう一度私はそれを使って穴を掘りました - 特にスレッディングの面で。早い段階であまりにも多くの静的なメンバーがいなくても働く方法を学ぶのが最善です。 –

+0

OODやメンテナンス可能なコードを書く方法を理解していないと、悪夢を作り出すことができますが、それは開発者の間違いでしょう。スレッディングに関する限り、開発者はスレッドセーフなコードの記述方法を理解するだけで済みます。 .Netには、これを支援する素晴らしいクラスがたくさんあります。 静的メンバーは、その場所を持ち、それらを理解することは、非常に重要なソフトウェア設計パターンにとって重要です。私は誰にも彼らから遠ざかるように言わないだろう。 – Rob

関連する問題