EventSubscription issue

Topics: CAB & Smart Client Software Factory
Sep 4, 2007 at 8:18 AM
I'm having some issues regarding the event publishing/subscription thing.

The EventPublication works nice and I can set a breakpoint and notice that the event is fired, but the EventSubscription method doesn't run.
In my first Presenter class I have the following:

EventPublication(EventTopicNames.MsiModelChange)
public event EventHandler<EventArgs<MsiModel>> MsiModelChange;

internal void UpdateModel()
{
if (MsiModelChange != null)
{
MsiModelChange(this, new EventArgs<MsiModel>(_msiModel));
}
}

and in a second Presenter class, that should grab some data from the MsiModel object passed in from the first presenter class, looks like this:

EventSubscription(EventTopicNames.MsiModelChange)
internal void LoadCollectionForm(object sender, EventArgs<MsiModel> e)
{
_collectionModel.CollectionName = e.Data.ProductName;
View.BindToCollectionModel(_collectionModel);
}

But this method never executes? Could someone please explain to me what I'm doing wrong, what I don't understand about the whole publish/subscribe thing?

Sep 4, 2007 at 12:47 PM
The problem might be of scope. Events can be published to different scopes, and this is defined in the EventPublication attribute, when you write:
[EventPublication(EventTopicNames.MsiModelChange, PublicationScope.Global)]
where PublicationScope has three values:
  1. Global
  2. WorkItem
  3. Descendants
i think the default is WorkItem but i'm not sure.

So the solution to your problem is either putting the subscribing presenter in the same workitem as the publisher (which might not be possible at this stage), or if you don't care for everyone to know when this event is fired, put it in Global.
Sep 4, 2007 at 1:11 PM
Thank for the the relpy, but the two presenter classes live in the same WorkItem. They are acually each part of a SmartPart that is shown in a DeckWorkspace according to the selection in a tree view if that makes the picture clearer.

And I've tried all three PublicationScopes but none worked :(

Sep 5, 2007 at 4:44 PM
The reason is that your event handler is declared as internal - it must be public!
This is one of the things that really annoys me:
You'll get lots of FxCop "ReviewVisibleEventHandlers"-issues because of that. It would be much better if EventInspector.ProcessPublishers() / EventInspector.ProcessSubscribers() would
search for non-public members, too (maybe only if there's an attribute on the class that explicitely states this). I'll propose this in the issue tracker now ;-)
Sep 5, 2007 at 7:37 PM
Thanks Steven... I'll change my methods to public, and I agree with you that it would be nice if it looked for non-public members too.
Sep 6, 2007 at 6:40 AM
I'd like to correct myself - the default of the scope is Global.
Sep 6, 2007 at 6:51 AM
@DaCheeseMan: just uploaded a patch. Let's see if they'll integrate that patch for the next version
Sep 6, 2007 at 8:41 AM
Edited Sep 6, 2007 at 8:46 AM
I changed my code to the following with no result:

Presenter 1
EventPublication(EventTopicNames.CollectionModelChange)
public event EventHandler<EventArgs<CollectionModel>> ModelUpdate;

public void ModelUpdated()
{
if (ModelUpdate != null)
{
ModelUpdate(this, new EventArgs<CollectionModel>(_collectionModel));
}
}

Presenter 2
EventSubscription(EventTopicNames.CollectionModelChange)
public void LoadCollectionModel(object sender, EventArgs<CollectionModel> e)
{
_collection = e.Data;
}

Both presenters reside in the same WorkItem and stil no success... Hmm???
As I stated before, I have two break points in each method but only the first (the one in ModelUpdate) gets hit. The one in LoadCollectionModel isn't hit.
"Strange, I believe it is" as Yoda would say...
Sep 6, 2007 at 9:11 AM
After some googeling I found a guy with a similar problem. The solution?
Change the event to the following...

Presenter 1
EventPublication(EventTopicNames.CollectionModelChange)
public event EventHandler ModelUpdate; //<EventArgs<CollectionModel>> ModelUpdate;

public void ModelUpdated()
{
if (ModelUpdate != null)
{
ModelUpdate(this, new EventArgs<CollectionModel>(_collectionModel));
}
}

And keep the subscriber as before...

Presenter 2
EventSubscription(EventTopicNames.CollectionModelChange)
public void LoadCollectionModel(object sender, EventArgs<CollectionModel> e)
{
_collection = e.Data;
}

Finally!
Now I have another problem but that's a more reasonable one I should sort out myself I hope :)
Sep 17, 2007 at 9:25 AM
Edited Sep 17, 2007 at 9:25 AM
Hi

I've got a problem similar to yours...
but, in my code, your solution doesn't work!

I've put my event publication in my ModuleController class..this is the code:

EventPublication(EventTopicNames.GroupSelected,PublicationScope.Global)
//public event EventHandler<EventArgs<string>> OnGroupSelected;
public event EventHandler OnGroupSelected;

The event is been subscribed by the following code:

EventSubscription(EventTopicNames.GroupSelected)
public void Prova(Object sender, EventArgs<string> buttonID)
{
Console.WriteLine("---< " + buttonID.Data);
}

I've pu the EventSubscription tagged method in two places:
- in the ModuleController class
- in a presenter of a view generated by the Add view with presenter recipe...

When the event is raised, only the subscription in the ModuleController class print something in Console...
I pinpoint that in each class the using directirve specifies the Infrastructure.Interface.Constants namespace...

where is the problem?
Does I wrong anything?

thanks
Leo
Sep 17, 2007 at 10:47 AM
Hi,
first you should re-enable
public event EventHandler<EventArgs<string>> OnGroupSelected;

That's the correct signature.

Then check if your view gets created by the object builder: set a breakpoint into the c'tor, let the program run and look at the callstack. If the
view is not created by the object builder, you'll create it explicitely with new. Replace that by
yourWorkItem.SmartParts.AddNew<YourViewClass>();

Also ensure that the view class is marked with the SmartPart-attribute.

mfg Steven