Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use events and delegate to send data between forms?

I need to create a Windows Form application that able to send data and to receive data from another Form instance. what mean, the Form is a publisher and a subscriber, both of them.

Unfortunately, I was sick that day, and I couldn't be in the lecture that day.

I'll explain again:

I have a small chat Form, who have: new Instance button, received messages, and send message.

as you can see right below:

enter image description here

When I send a message, it will be shown in the "Recieved" textbox of ALL INSTANCES.

I guess that I need to use delegates and events.

How to do so? thanks!!

like image 384
Billie Avatar asked Dec 05 '12 08:12

Billie


People also ask

How are delegates used in event handling?

A delegate is a way of telling C# which method to call when an event is triggered. For example, if you click a Button on a form, the program would call a specific method. It is this pointer that is a delegate. Delegates are good, as you can notify several methods that an event has occurred, if you wish so.

What is the use of delegates and events in C#?

A delegate is an object which refers to a method or you can say it is a reference type variable that can hold a reference to the methods. Delegates in C# are similar to the function pointer in C/C++. It provides a way which tells which method is to be called when an event is triggered.


1 Answers

Here's a quick solution.. Let me know if you have any questions or if you find the comments confusing..

Here's the Form class (code behind). Notice that once the form is instantiated, it "subscribes" to an event by "wiring" an event handler to the HandleMessage event inside the Message class. Within the Form class, this is where the ListView's item collection is populated.

Whenever the New Form button is clicked, the same Form get's created and displayed (this allows for code re-use, since the same logic will be exactly the same for all instances of the Form)

public partial class Form1 : Form
{
    Messages _messages = Messages.Instance; // Singleton reference to the Messages class. This contains the shared event
                                            // and messages list.

    /// <summary>
    /// Initializes a new instance of the <see cref="Form1"/> class.
    /// </summary>
public Form1()
{
    InitializeComponent();

    // Subscribe to the message event. This will allow the form to be notified whenever there's a new message.
    //
    _messages.HandleMessage += new EventHandler(OnHandleMessage);

    // If there any existing messages that other forms have sent, populate list with them.
    //
    foreach (var messages in _messages.CurrentMessages)
    {
        listView1.Items.Add(messages);
    }
}

/// <summary>
/// Handles the Click event of the buttonNewForm control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void buttonNewForm_Click(object sender, EventArgs e)
{
    // Create a new form to display..
    //
    var newForm = new Form1();
    newForm.Show();
}

/// <summary>
/// Handles the Click event of the buttonSend control. Adds a new message to the "central" message list.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void buttonSend_Click(object sender, EventArgs e)
{
    string message = String.Format("{0} -- {1}", DateTime.UtcNow.ToLongTimeString(), textBox1.Text);
    textBox1.Clear();
    _messages.AddMessage(message);
}

/// <summary>
/// Called when [handle message].
/// This is called whenever a new message has been added to the "central" list.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
public void OnHandleMessage(object sender, EventArgs args)
{
    var messageEvent = args as MessageEventArgs;
    if (messageEvent != null)
    {
        string message = messageEvent.Message;
        listView1.Items.Add(message);
    }
}

}

Here's a Messages class that I created to handle a "central" list of messages that are sent between Forms. The Messages class is a singleton (meaning, it can be instantiated only once), which allow one list to be persisted throughout all instances of a Form. All Forms will share the same list, and get notified whenever a list has been updated. As you can see, the "HandleMessage" event is the Event that each Form will subscribe to whenever it has been created/shown.

If you take a look at the NotifyNewMessage function, this is called by the Messages class to notify the subscribes that there was a change. Since EventArgs are used to pass data to the subscribers, I've created a special EventArgs to pass the newly added messages to all subscribers.

class Messages
{
    private List<string> _messages = new List<string>();
    private static readonly Messages _instance = new Messages();
    public event EventHandler HandleMessage;

    /// <summary>
    /// Prevents a default instance of the <see cref="Messages"/> class from being created.
    /// </summary>
    private Messages() 
    {
    }

    /// <summary>
    /// Gets the instance of the class.
    /// </summary>
    public static Messages Instance 
    { 
        get 
        { 
            return _instance; 
        } 
    }

    /// <summary>
    /// Gets the current messages list.
    /// </summary>
    public List<string> CurrentMessages 
    {
        get
        {
            return _messages;
        }
    }

    /// <summary>
    /// Notifies any of the subscribers that a new message has been received.
    /// </summary>
    /// <param name="message">The message.</param>
    public void NotifyNewMessage(string message)
    {
        EventHandler handler = HandleMessage;
        if (handler != null)
        {
            // This will call the any form that is currently "wired" to the event, notifying them
            // of the new message.
            handler(this, new MessageEventArgs(message));
        }
    }

    /// <summary>
    /// Adds a new messages to the "central" list
    /// </summary>
    /// <param name="message">The message.</param>
    public void AddMessage(string message)
    {
        _messages.Add(message);
        NotifyNewMessage(message);
    }
}

/// <summary>
/// Special Event Args used to pass the message data to the subscribers.
/// </summary>
class MessageEventArgs : EventArgs
{
    private string _message = string.Empty;
    public MessageEventArgs(string message)
    {
        _message = message;
    }

    public String Message
    {
        get
        {
            return _message;
        }
    }
}

Also.. in order for the messages to be "displayed" correctly, don't forget the set the "View" property of the ListView control to "List". An easier (and preferred way) would simply be using the ObservableCollection list type, which already provides an event you can subscribe to.

Hope this helps.

like image 174
d.moncada Avatar answered Sep 18 '22 15:09

d.moncada