electricalbah
electricalbah

Reputation: 2297

Subscribe to event of an object which is not yet created?

Well I really doubt if this is possible, but maybe after all it maybe. I want to subscribe to an event when my program initialize but the object will be created long after my form load. At the time of subscription, the object is null, but later its created. Is it possible to update that object so that the event will fire?

In the Form_Load, I subscribe like this

  this.mediaCenter.ItemManager.Root.SetProgressBar += (val) => 
        { 
             this.Invoke((Action)(() =>
            {
                this.progressBarControl1.Position = val;
            }));
        };

In Item Manager, the object is null during form load

   private ItemContainerRoot _myRoot;
        public ItemContainerRoot Root
        {
            get { return this._myRoot; }
        }

Later my Database will get the object

this._myRoot = context.GetTable<Item>().Single(a => a.Id == 0) as ItemContainerRoot;

Upvotes: 1

Views: 258

Answers (2)

rareyesdev
rareyesdev

Reputation: 2427

Try this:

In Class Library notify when Root property changes and use the property (not the field) everywhere.

class ItemManager : INotifyPropertyChanged
{
    private ItemContainerRoot _myRoot;
    public ItemContainerRoot Root
    {
        get { return _myRoot; }

        set
        {
            _myRoot = value;
            OnPropertyChanged("Root");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}    

In UI subscribe to the property changed event of the ItemManager after initialization:

ItemManager.PropertyChanged += (o, args) =>
{
     if (args.PropertyName == "Root" && ItemManager.Root != null)
     {
          ItemManager.Root.SetProgressBar += (val) =>
          {
               this.Invoke((Action)(() =>
               {
                    this.progressBarControl1.Position = val;
               }));
          };
     }
};

Upvotes: 1

Enigmativity
Enigmativity

Reputation: 117084

If you really want to do this properly you need to jump through a few hoops:

private Action _myRootDisconnect = null;
private object _myRootGate = new object();
private ItemContainerRoot _myRoot;
public ItemContainerRoot Root
{
    get { return _myRoot; }
    set
    {
        lock (_myRootGate)
        {
            Action<int> setProgressBar = val =>
            {
                this.Invoke((Action)(() =>
                {
                    this.progressBarControl1.Position = val;
                }));
            };

            if (_myRootDisconnect != null)
            {
                _myRootDisconnect();
                _myRootDisconnect = null;
            }

            _myRoot = value;
            _myRoot.SetProgressBar += setProgressBar;

            _myRootDisconnect = () =>
            {
                _myRoot.SetProgressBar -= setProgressBar;
            };
        }
    }
}

Basically this code is wiring up your event whenever you assign the instance to the property - not the field.

It's got a lock because you're obviously calling this code from another thread (but I don't know why).

It's also creating an Action called _myRootDisconnect to enable you to disconnect the event whenever you reassign Root (or when you are cleanly exiting your code.)

Upvotes: 0

Related Questions