Using Event Aggregation for common messages - failing when publishing multiple messages

Topics: Prism v4 - WPF 4
Oct 10, 2012 at 7:41 PM

I have a Prism (v4.0, WPF) app that I am working on.  It has various UI modules that make async wcf calls using the generated async methods.  When those fail in the ...Completed async handler, I publish an event using the EventAggregator that the shell has subscribed to -- and the logic there displays a Notification interaction request.

In one of my modules I have two async wcf service calls, and when they both fail, I get an event published from BOTH of their Completed handlers.

The subsriber code then throws an exception:

Specified Visual is already a child of another Visual or the root of a CompositionTarget.

 The shell  is subscribing to the event on the UIThread.  All works well when only one wcf call fails (and only one event is raised/published).

I'm just trying to get it so that I can see both messages -- it's ok that they would be synchronous/sequential to the user.  Any help and guidance would be appreciated.

Here is the code that subscribes to the event:

public void OnImportsSatisfied()
        {
            _eventAggregator.GetEvent<NwpNotficationEvent>().Subscribe(OnNwpNotificationRequest, ThreadOption.UIThread);
        }

        private void OnNwpNotificationRequest(NwpNotificationContent obj)
        {
            _systemMessage.Raise(new Notification { Content = obj, Title = "NWP Billing Services"});
        }
Here is the XAML code for the message box:
<prism:InteractionRequestTrigger SourceObject="{Binding SystemMessage}">
                <interactionRequest:InteractionDialogAction>
                    <interactionRequest:InteractionDialogAction.Dialog>
                        <interactionRequest:NotificationLocalModalInteractionDialog />
                    </interactionRequest:InteractionDialogAction.Dialog>
                    <interactionRequest:InteractionDialogAction.ContentTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Vertical">
                                <TextBlock Text="{Binding Message}" Margin="5,0,5,0" TextWrapping="Wrap" FontSize="12" VerticalAlignment="Center" />
                                <TextBox Text="{Binding Details}" Margin="5,0,5,0" TextWrapping="Wrap" FontSize="12" VerticalAlignment="Center" />
                            </StackPanel>                            
                        </DataTemplate>
                    </interactionRequest:InteractionDialogAction.ContentTemplate>
                </interactionRequest:InteractionDialogAction>
            </prism:InteractionRequestTrigger>
Developer
Oct 11, 2012 at 5:12 PM

Hi,

Based on my understanding if you are using the InteractionDialogAction provided in Karlshifflett's In the Box – MVVM Training or a similar implementation, I believe the cause of this error could be that when the second call is raised, if the first message is still showing, the InteractionDialogAction will try to add the same InteractionDialogBase to the AssociatedObject's Children property twice generating the aforementioned exception.

In my opinion, a possible workaround for this could be to set a busy flag that will change its state in your event handler, and only raise the interaction request if the flag is not busy. Then if another event is raised when the flag is busy, you could avoid raising the interaction request and store the new published notification object in a collection like a queue. This way you could pass a callback when raising the interaction request, which will be called when closing the displayed message, and in this callback you could check if the queued notification objects collection is not empty and raise a new interaction request if necessary, if not you could change back the state of the flag to not busy.

I hope you find this helpful,

Agustin Adami
http://blogs.southworks.net/aadami