Sharing user control between views

Topics: Getting Started
Sep 9, 2013 at 3:05 AM
Hi,
I have a child View (and corresponding VM) that wraps some common functionality (similar to ASP.NET user control). I have two parent views that reference this view the same way
<ContentControl x:Name="AccountsViewModel" HorizontalAlignment="Stretch" />
with ViewModel backing
       private AccountSelectorViewModel accountsViewModel;
       public AccountSelectorViewModel AccountsViewModel
       {
            get { return accountsViewModel; }
            set
            {
                accountsViewModel = value;
                NotifyOfPropertyChange(() => AccountsViewModel);
            }
       }
The parent viewmodels use an importing constructor to resolve the child VM and the constructor assigns this via the property setter.

My original problem was the user control was being shared between my parent views and I needed it to be separate instances.

So I added
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.NonShared)]
to the export definition of the child ViewModel and added a counter to the child ViewModel to track how many times it got created.

My parent views are in a tabcontrol loaded by MEF in the ShellViewModel using and ImportMany. Each parent gets created as expected

Parent A - Count 0
Parent B - Count 1

However when the screen loads and Parent A is activated, it gets created again. When I select Parent B it gets created again. So I now have 4 instances.

Parent A - Count 0 (from ShellViewModel)
Parent B - Count 1 (from ShellViewModel)
Parent A - Count 2 (from Activate)
Parent B - Count 3 (from Activate by clicking on tab)

This causes a problem because the child view is publishing a message to the parent views which Handle() the message. The parameter is the child VM.

Both parents receive the message, but the child instance has count 2 as this is what is being displayed and not the one with count 0. I am referencing the child view to set properties on the parent.

Why am I getting the extra VMs and how do I get rid of them so that the message passing works correctly.

Regards
Alan
Sep 10, 2013 at 12:01 AM
Ok, I found the issue. MEF was loading the child VM when the Shell did an ImportMany but my child view was being bound to the ViewModel by a cal:Bind:Model as well. By removing the cal:Bind:Model which I didn't need everything seems to work as expected.

I'm just left with the issue that the Publish event has two subscribers both listening to the same message type - both Handle the message but I'd them to only do so if the message was for them.

Regards
Alan
Sep 12, 2013 at 6:06 AM
Then just Pass an object in the eventaggregator in which you can Set some property which states for what view this Message is for (e.g. some enum)