Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wiring up the MVVM View and ViewModel using Declarative DataContext for Design-Time and Data Template for Runtime?

Is it possible to wire up the View and ViewModel using both a Declarative DataContext and a Data Template?

Goal: I want to wire Views with a one ViewModel for design-time and another at run-time. Currently, using a Declarative DataContext for a design-time VM and a Data-Template-specified VM for runtime doesn't behave as expected.

Background - There are a variety of ways to wire up a View and ViewModel including the following:

A.) Declaratively specify the ViewModel DataContext within the View’s XAML. This technique is useful at Design-Time using the parameter-less constructor to pass in dummy data.

<UserControl.DataContext>
    <my: BrowseAssetsViewModel />
</UserControl.DataContext>

B.) Programmatically specify the ViewModel, View and DataContext.

// …Setup code
BrowseAssetsViewModel viewModel = new BrowseAssetsViewModel(assetRegistry, domains);
BrowseAssetsView view = new BrowseAssetsView();
view.DataContext = viewModel;

When Approach B is used in combination with Approach A, at run-time WPF overrides the default DataContext specified in Approach A using the version of the ViewModel with the parameterized constructor specified in Approach B.

C.) Define a Data Template for the View-ViewModel association By associating a View and ViewModel in App.XAML Application.Resources, WPF can wire up the correct View based on a ViewModel’s type.

<DataTemplate DataType="{x:Type vm: BrowseAssetsViewModel }">
    <vw: BrowseAssetsView />
</DataTemplate>

If a ViewModel property were bound to a ContentPresenter control, WPF would wire-up the corresponding View (based on the ViewModel’s type) and place it within the ContentPresenter. This is useful in the “ViewModel-first” scenario where the ViewModel is presented and WPF resolves and wires the correct View by inspecting the presented ViewModel’s type.

Problem - When using this Approach C in combination with Approach A, WPF resolves the correct View but it seems to then re-query the View, calling the declaratively specified ViewModel via the parameter-less constructor (Approach A), thus overriding the existing ViewModel property!

Question - Is there a way to use these techniques (C and A) together without A inadvertently overwriting the C ViewModel property?

like image 231
Lawrence P. Kelley Avatar asked Nov 14 '11 21:11

Lawrence P. Kelley


1 Answers

You can specify that the DataContext is in case A set only only at design time, like so:

<UserControl ...
    d:DataContext="{d:DesignInstance my:BrowseAssetsViewModel}"
>

For details, see Using a DesignInstance... on MSDN.

like image 94
Reed Copsey Avatar answered Oct 22 '22 00:10

Reed Copsey