2011-07-06 11 views
-1

私はStreamからデータを受け取るクラスClientを持っています。他のクラスの変更についてMainWindowに通知します

また、私はListBoxを持つMainWindowを持っています。

基本的には、新しいデータを受け取ったときにListBoxに項目を追加する必要があります。参照してくださいコードここ

class Client 
{ 
    private TcpClient client; 
    private NetworkStream stream; 
    private ASCIIEncoding encoder; 
    private Thread clientThread; 

    public Client(string ip, int port) 
    { 
     this.client = new TcpClient(ip, port); 
     this.stream = client.GetStream(); 
     this.encoder = new ASCIIEncoding(); 

     clientThread = new Thread(Receive); 
     clientThread.Start(); 
    } 

    public void Receive() 
    { 
     byte[] data = new byte[4096]; 
     int bytesRead; 

     bytesRead = stream.Read(data, 0, 4096); 
     string[] message = DecodeMessage(data, bytesRead); 
     // TODO: Notify about new message 
    } 

はあなたがタイプ

ObservableCollection<string> ChatMessages{get;private set;} 

このコレクションのクライアントクラスのメンバーとプロパティを作成することができ、私のメインウィンドウ

public partial class MainWindow : Window 
{ 
    Client client; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     client = new Client("127.0.0.1", 2020); 
    } 

    public void updateChat(string[] message) 
    { 
     // TODO: Should add new messages into ListBox 
    } 

    private void send_Click(object sender, RoutedEventArgs e) 
    { 
     client.Send(0, this.messageBox.Text); 
     this.messageBox.Clear(); 
    } 
} 
+0

http://msdn.microsoft.com/en-us/library/awbftdfh.aspxなぜコメントを落とし、少なくともせずに、この質問downvote? –

+0

私の悪い英語のためかもしれませんか? :) –

答えて

0

星で囲まれた部分に注意してコードを記述してください。

//***** 
public class MessageEventArgs : EventArgs 
{ 
    public string[] Message { get; set; } 
    public MessageEventArgs(string[] message) 
    { 
     Message = message; 
    } 
} 
//***** 

public class Client 
{ 
    private TcpClient client; 
    private NetworkStream stream; 
    private ASCIIEncoding encoder; 
    private Thread clientThread; 
    //***** 
    public event EventHandler<MessageEventArgs> MessageReceived 
    //***** 

    public Client(string ip, int port) 
    { 
     this.client = new TcpClient(ip, port); 
     this.stream = client.GetStream(); 
     this.encoder = new ASCIIEncoding(); 

     clientThread = new Thread(Receive); 
     clientThread.Start(); 
    } 

    public void Receive() 
    { 
     byte[] data = new byte[4096]; 
     int bytesRead; 

     bytesRead = stream.Read(data, 0, 4096); 
     string[] message = DecodeMessage(data, bytesRead); 
     //***** 
     InvokeMessageReceived(new MessageEventArgs(message)); 
     //***** 
    } 

    //***** 
    protected void InvokeMessageReceived(MessageEventArgs e) 
    { 
     EventHandler<MessageEventArgs> handler = MessageReceived; 
     if (handler != null) handler(this, e); 
    } 
    //***** 
} 

public class MainWindow : Window 
{ 
    Client client; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     client = new Client("127.0.0.1", 2020); 
     //***** 
     client.MessageReceived +=new EventHandler<MessageEventArgs>(client_MessageReceived); 
     //*****   
    } 

    //***** 
    void client_MessageReceived(object sender, MessageEventArgs e) 
    { 
     var message = e.Message; 
     foreach (var s in message) 
     { 
      listBox1.Items.Add(s); 
     } 
    } 
    //***** 

    public void updateChat(string[] message) 
    { 
     // TODO: Should add new messages into ListBox 
    } 

    private void send_Click(object sender, RoutedEventArgs e) 
    { 
     client.Send(0, this.messageBox.Text); 
     this.messageBox.Clear(); 
    } 
} 

だけでなく、これをお読みください:イベント(C#プログラミングガイド)

+0

これは、私の投稿に記載されているuiスレッド以外のスレッドから項目を変更する際にスレッドの問題が発生します。一方、ディスパッチャーを使用することは実行可能な解決策になります。私の唯一の懸念は、それが本当にwpf'ishではないということです。しかし、一方で、それは疑問ではなかった:) – dowhilefor

+0

@dowhileforあなたは実際に正しい。私はすべてのスレッドについて考えていなかった、正直に気づかなかった:( –

1

です(TODOラインに注意を払います) ListBoxプロパティItemsSourceにバインドされています。あなたが何かを削除する場合

myListBox.ItemsSource = client 

あなたは今、毎回あなたがリストに1つの項目を追加

<ListBox x:Name="myListBox ... 

を使用し、XAMLでのListBoxに名前を付ける必要があるかもしれません、ビューは自動的に同じ、更新されます。

発生する1つの問題は、スレッドの使用に関するものです。 UIのすべての操作は、UIスレッドで呼び出される必要があります。このコレクションは、UIスレッド以外のスレッドで表示にバインドされていてはなりません(スレッドがメッセージを受信して​​いることを考慮すると明らかですが、Dispatcherを利用できます)。別のスレッドからコレクションを変更する場合は、を使用してください。このようにして、ディスパッチャが関連するスレッドで呼び出すまで、呼び出しは延期されます。その場合、UIスレッドが呼び出されます。

mUIDispatcher.Invoke(DispatcherPriority.Normal, 
     (Action)(() => { ChatMessages.Add(myMessage); })); 

私は役立つことを望みます。 WPFのコンセプトに慣れるのは難しいですが、Windowsフォームやそれに類似した背景から来ても、私はあなたに価値があることを保証します:)

+0

私は質問がWinFormsアプリケーションのためだと信じています。 –

+0

WPF用にタグが付けられています。 – SergioL

関連する問題