miken
miken

Reputation: 387

Fire an event when a list in a different class is added to C#

I have a static list in a class that handles database functions. If any of the methods throw an exception, I am adding the exception details to the list. I wanted to trigger an event anytime an item is added to the list, and display the message in a MessageBox in a different class, in this case, a Windows Forms class. What is the best way to handle the event in the Forms class if the static list in the database class is added to?

class DatabaseClass
{
    // Static list for messages.
    public static List<string> messages = new List<string>();

    public static DataTable GetOrders()
    {
        var dt = new DataTable();
        var sql = "select * from orders";

        using (SqlConnection conn = new SqlConnection(ConString.Orders()))
        using (SqlCommand cmd = conn.CreateCommand())
        {
            try
            {
                cmd.CommandText = sql;
                conn.Open();
                dt.Load(cmd.ExecuteReader());
            }
            catch (Exception ex)
            {
                // Want to trigger an event when the list is added to.
                messages.Add("Problem getting orders. " +
                    ex.ToString());
            }
        }
        return dt;
}

public partial class Form1 : Form
{  
    // When the event in the DatabaseClass is triggered, 
    // display a message box with the message from the list. 
}

Upvotes: 1

Views: 128

Answers (2)

LarsTech
LarsTech

Reputation: 81635

You can use the BindingList<T> class from the System.ComponentModel namespace in place of the List<T> class because it contains events you are looking for:

class DatabaseClass
{
  // Static list for messages.
  public static BindingList<string> Messages = new BindingList<string>();

Then in your form, you can simply listen for any changing events:

public partial class Form1 : Form
{
  public Form1() {
    InitializeComponent();
    DatabaseClass.Messages.ListChanged += Messages_ListChanged;
  }
}

void Messages_ListChanged(object sender, ListChangedEventArgs e) {
  if (e.ListChangedType == ListChangedType.ItemAdded) {
    MessageBox.Show(DatabaseClass.Messages[e.NewIndex].ToString());
  }
}

Upvotes: 2

C4d
C4d

Reputation: 3292

You just have to define an EventHandler inside your DatabaseClass and call it when the list gets set. Then hook up to the event:

class DatabaseClass
{
    public static event EventHandler ErrorsChanged;

    private static List<string> messages = new List<string>();
    public static List<string> Messages
    {
        get
        {
            return messages;
        }
        set
        {
            messages = value;
            ErrorsChanged(messages, EventArgs.Empty);
        }
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        DatabaseClass.ErrorsChanged += new EventHandler(ErrorItemsChanged);
    }

    private void ErrorItemsChanged(Object sender, EventArgs e)
    {
        // This line will be entered if the list has changed.
    }
}


OR if you want to be cool, you can extend List<T> by that event:

public class ListEx<T> : List<T>
{
    public event EventHandler OnItemChange;

    public new void Add(T item)
    {
        base.Add(item);
        OnItemChange(this, EventArgs.Empty);
    }
}

Then use it this way:

public class DatabaseClass
{
    // Use extended List here.
    public static ListEx<string> messages = new ListEx<string>();
}

public partial class Form1 : Form
{
    public Form1()
    {
        DatabaseClass.messages.OnItemChange += new EventHandler(ItemChanged);
    }

    public void ItemChanged(Object sender, EventArgs e)
    {
        // Will be raised.
    }
}

Upvotes: 1

Related Questions