开发者

Notify MainWindow about change in other class

开发者 https://www.devze.com 2023-03-17 12:26 出处:网络
I have class Client, which is receives data from Stream. Also I have MainWindow, which has ListBox. Basically I need to add item in ListBox when new data received. Please see codes (pay attention to

I have class Client, which is receives data from Stream.

Also I have MainWindow, which has ListBox.

Basically I need to add item in ListBox when new data received. Please see codes (pay attention to TODO lines)

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
    }

Here is my MainWi开发者_StackOverflow中文版ndow

 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();
    }
}


You could create a member and property in the Client class of type

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

This collection is bound to your ListBox property ItemsSource.

myListBox.ItemsSource = client

you might need to give the ListBox a name in XAML, use

<ListBox x:Name="myListBox ...

Now everytime you add one item into the list, the view gets automatically updated, the same if you remove something.

One problem that will arise is regarding the use of threads. Every operation on the UI must be called in the UI thread. You must not change this collection, bound to the view, in another thread than the UI thread(which is obviously the case, considering your thread listening for messages), but for that you can utilize the Dispatcher. If you want to modify the collection from another thread, you just use the Invoke method. That way the call will be postponed until the dispatcher calls it in the associated thread, that case the ui thread.

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

I hope that helps. Its difficult to get used to the WPF concept, when coming from a Windows Forms or similar background, but i guarantee you its worth it :)


Please see the code bellow paying attention to parts surrounded by stars.

//*****
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();
    }
}

Please read this as well: Events (C# Programming Guide) http://msdn.microsoft.com/en-us/library/awbftdfh.aspx

0

精彩评论

暂无评论...
验证码 换一张
取 消