4

first of all i'm kinda new to C#

I'm trying to do something like this in a C# winforms application

when my app starts, a form starts minimized in the system tray. when i double click it, it opens and sends a request to a qpid broker for some info. then a message is sent back, and received in a listener in my app (i'm not sure code is relevant but i'll post it anyway)

namespace MyApp
{
    public class MyListener : IMessageListener
    {
        public void MessageTransfer(IMessage m)
        {
            //do stuff with m
        }
    }
}

what i'm trying to do is populate a listbox that's in that form with the message received in that function, but i have no idea how to communicate with that specific form from the MessageTransfer function

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
Andrei S
  • 6,486
  • 5
  • 37
  • 54

2 Answers2

5

I would suggest that your listener has no knowledge about how the messages are to be presented. Instead, expose an event that the form can listen to:

// event args class for transmitting the message in the event
public class MessageEventArgs : EventArgs
{
    public IMessage Message { get; private set; }

    public MessageEventArgs(IMessage message)
    {
        Message = message;
    }
}

In your listener class:

public class MyListener : IMessageListener
{
    public event EventHandler<MessageEventArgs> MessageReceived;

    public void MessageTransfer(IMessage m)
    {
        OnMessageReceived(new MessageEventArgs(m));
    }

    protected void OnMessageReceived(MessageEventArgs e)
    {
        EventHandler<MessageEventArgs> temp = MessageReceived;
        if (temp != null)
        {
            temp(this, e);
        }
    }
}

Now you can add an event listener in your form and add the message information to a listbox or any other kind of control you like.

Update
Here is an example on how to hook up the event handler in the form. This code makes two assumptions:

  • The event MessageReceived is defined in the IMessageListener interface
  • The IMessage interface has a property called Text.

Code sample:

public partial class MainUI : Form
{
    private IMessageListener _messageListener;

    public MainUI()
    {
        InitializeComponent();
        _messageListener = new MyListener();
        _messageListener.MessageReceived += MessageListener_MessageReceived;
    }

    void MessageListener_MessageReceived(object sender, MessageEventArgs e)
    {
        _messageListBox.Items.Add(e.Message.Text);
    }

}
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • thanx for the fast reply! this might sound pretty stupid.. but how (and on what) do i add an event listener in the form? (my guess is i have to edit Form1.Designer.cs, and in the Form1 section add something like this.onMessageReceived += new System.EventHandler(this.Form1_DoStuffWithMessage) – Andrei S May 17 '10 at 08:00
  • thanks, that helped, and almost did the trick, but i now have another problem: whenever the MessageListener_MessageReceived function is called i get a "System.InvalidOperationException: Cross-thread operation not valid: Control 'ticketList' accessed from a thread other than the thread it was created on.", ticketList being my listbox – Andrei S May 17 '10 at 13:37
  • 1
    @andrew: I think this SO answer might help you out: http://stackoverflow.com/questions/1377529/cross-thread-operation-not-valid/1377558#1377558 – Fredrik Mörk May 17 '10 at 13:55
  • ha, awesome, i was just reading that one! guess it works now.. thanks again – Andrei S May 17 '10 at 14:04
1

If your forms holds the listener the simplest way is to create an event that the listener will rise for each message that is being transfered.

  1. add the following to your listener class:

    public delegate void MessageHandler(IMessage m);
    public event MessageHandler MessageReceived;
    
  2. add the following to your MessageTransfer method:

        if (MessageReceived != null)
            MessageReceived(m);
    
  3. Now in your form you can attach a method for the event you just created:

The following line should be placed in the form after you initialize the listener:

    _listener.MessageReceived += new MessageHandler(Form1_MessageReceived);

The following method should me placed in the form itself:

    void Form1_MessageReceived(IMessage m)
    {
        // add the message to the list
    }

There is one more thing you need to do if the listener is running on a different thread, and thats to invoke another method in the forms thread to modify the list.

Ronny
  • 2,399
  • 3
  • 20
  • 27