user1309226
user1309226

Reputation: 759

How are PRISM V4 Views loaded without parameterised constructor?

I have a question about the way Views are loaded. I have this sample code shown below of a view that loads correctly:

    [ViewExport(RegionName = RegionNames.LeftRegion)]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class EmployeeListView : UserControl
{
    [ImportingConstructor]
    public EmployeeListView(EmployeeListViewModel viewModel)
    {
        InitializeComponent();
        //this.DataContext = viewModel;
    }

    [Import]
    public EmployeeListViewModel Model
    {
        get
        {
            return DataContext as EmployeeListViewModel;
        }
        set
        {
            DataContext = value;
        }
    }
}

Notes about above code:

  1. I added an [ImportingConstructor] attribute to a parameterized constructor which is passing in the ViewModel.
  2. I also have an [Import] attribute for the ViewModel setter so I can assign the DataContext.

However, in the Stocktrader demo the loading of the views is done differently. Look for example at the PositionSummaryView.xaml.cs file.

[ViewExport(RegionName = RegionNames.MainRegion)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class PositionSummaryView : UserControl
{
    public PositionSummaryView()
    {
        InitializeComponent();
    }

    #region IPositionSummaryView Members

    [Import]
    public IPositionSummaryViewModel Model
    {
        get
        {
            return DataContext as IPositionSummaryViewModel;
        }
        set
        {
            DataContext = value;
        }
    }
    #endregion
}

My questions are the following:

  1. How is the View being instantiated without the [Importing Constructor] attribute for the class as shown in previous example?
  2. What triggers the assignment of the DataContext property? How is value being passed to the ViewModel property? Whilst playing around with a modified version of StockTrader I created a new view. if I place a breakpoint next to the line DataContext = value, the breakpoint is never hit.

Upvotes: 2

Views: 566

Answers (1)

Matthew Abbott
Matthew Abbott

Reputation: 61589

There is little point on adding [ImportingConstructor] to your constructor, if you don't intend to do anything with that in your constructor. On the flip side, if your instance of EmployeeListViewModel is a required dependency for EmployeeListView, then you probably should be passing it in via the constructor.

Having dual imports will cause the following:

  1. The type will be constructed with the [ImportingConstructor] attribute allowing the instance of EmployeeListViewModel to be injected.
  2. The property Model will be injected with an instance of EmployeeListViewModel after the type has been instantiated.

Should EmployeeListViewModel do any heavy lifting during instantiation (e.g. accessing a database or service), and is created as a non-shared part ([PartCreationPolicy(CreationPolicy.NonShared)]), then you are unnecessarily instantiating the part twice and doubling your work. If the part is shared, this is less of an issue.

In answer to your questions though,

  1. MEF will implicity use the default constructor (PositionSummaryView() { }) for any types that do not have a constructor marked with ImportingConstructorAttribute. So in the case of the PositionSummaryView, it will check for an [ImportingConstructor] decoration attribute, will not find it, so will use the default constructor.
  2. The [Import] is satisfied after the type has been constructed. I'd be surprised that the breakpoint is not being hit though... I'd check your build mode (Debug | Release), etc.

Upvotes: 2

Related Questions