How to subscribe to C# GUI event from ProjectA in dll in ProjectB

387 Views Asked by At

I have a C# WPF GUI in ProjectA. I raise an event in ProjectA and want to subscribe/respond to that event from within ProjectB which is a dll that knows nothing about ProjectA. ProjectA has references to objects in ProjectB, but not vice versa.

For example, user clicks a button in ProjectA. Inside ProjectA's button_Click() handler it calls UserClickedButtonX(this, e). ProjectB should subscribe to the UserClickedButtonEvent and handle it when the event is raised.

The code below doesn't work since ProjectB doesn't know about 'MainWindow' in ProjectA. Thanks in advance!

In ProjectA (Mainwindow.xaml.cs):
        private void buttonX_Click(object sender, RoutedEventArgs e) {
            OnUserClickedButtonXEvent(new EventArgs());
        }

        public static event UserClickedButtonXEventHandler UserClickedButtonXEvent;
        public virtual void OnUserClickedButtonXEvent(EventArgs e) {
            if (UserClickedButtonXEvent!= null)
                UserClickedButtonXEvent(this, e);
        }

In Project B (dll):
           MainWindow.UserClickedButtonXEvent+= new UserClickedButtonXEventHandler(UserClickedButtonXFunction);

        void UserClickedButtonXFunction(object source, EventArgs e) {
            Console.WriteLine("User clicked Button X on the GUI in another project!");
        }
2

There are 2 best solutions below

1
On BEST ANSWER

You should be able to put this line into ProjectA (eg. MainWindow contructor):

MainWindow.UserClickedButtonXEvent += ProjectB.ClassB.UserClickedButtonXFunction;

Function has to be public static, or you have to create an instance of ClassB, eg. a singleton.

2
On

Consider using an EventAggregator to decouple classes from each other in regards to publish\subscribe events.

This pattern leverages messages (i.e. strings) that publishers and subscribers can leverage without knowing about each other.

[TestMethod]
public void eventaggregator()
{
    // Setup
    var subscription = "my_subscription";
    bool messageReceived = false;

    EventAggregator.Instance.Register(subscription, (parameter) =>
        {
            // Logic goes here...
            messageReceived = true;
        });

    // Test
    EventAggregator.Instance.Publish(subscription, "a parameter for subscibers");

    // Verify
    Assert.IsTrue(messageReceived);
}


public class EventAggregator
{
    #region Singleton
    static EventAggregator _eventAggregator = null;
    private EventAggregator() { }

    public static EventAggregator Instance
    {
        get
        {
            if (_eventAggregator == null)
            {
                _eventAggregator = new EventAggregator();
            }

            return _eventAggregator;
        }
    }
    #endregion

    List<Observer> _observers = new List<Observer>();

    public void Register(string subscription, Action<object> response)
    {
        var observer = new Observer() { Subscription = subscription, Respond = response };
        _observers.Add(observer);
    }

    public void Publish(string subscription, object payload)
    {
        foreach (var observer in _observers)
        {
            if (observer.Subscription == subscription)
            {
                observer.Respond(payload);
            }
        }
    }
}

public class Observer
{
    public string Subscription { get; set; }
    public Action<object> Respond {get; set; }
}