Black Dynamite
Black Dynamite

Reputation: 4147

WPF: Inject DataContext into DataTemplate View

I have a control that has a child ContentControl whose view is set through a DataTrigger and DataTemplate. What I would like to do, is set the DataContext of these controls to a property of my main DataContextViewModel. My view code looks like so.

    <UserControl.Resources>
        <DataTemplate x:Key="ManageTags">
            <local:TagsEditView DataContext="{Binding Path=TagsEditViewModel}">        
             </local:TagsEditView>
        </DataTemplate>
        <DataTemplate x:Key="ExportTags">
             <local:TagsExportView DataContext="{Binding Path=TagsExportViewModel}">
             </local:TagsExportView>
        </DataTemplate>
        <DataTemplate x:Key="ImportTags">
             <local:TagsImportView DataContext="{Binding Path=TagsImportViewModel}">
              </local:TagsImportView>
      </DataTemplate>

On the ViewModel of the containing view I have the following properties which I have confirmed are being set and updated correctly:

    public TagsExportViewModel TagsExportViewModel { get; set; }
    public TagsImportViewModel TagsImportViewModel { get; set; }
    public TagsEditViewModel TagsEditViewModel { get; set; }

All is fine till I Snoop the child views (TagsEditView,TagsImportView..) and then I see that the DataContext is not being set.

How on earth do I get these ViewModels into these views? Or am I going about this the wrong way?

Any help is greatly appreciated.

Upvotes: 1

Views: 677

Answers (3)

AnjumSKhan
AnjumSKhan

Reputation: 9827

You are using ContentControl and its ContentTemplate.

ContentTemplate is used to customize Content.

So, here in your case you have to set Content in your DataTrigger's Setter. And everything will fall in place. See sample below :

<DataTrigger Binding="{Binding CurrentVMindex}" Value="1">
  <Setter Property="Content" Value="{Binding VM1}"/>
  <Setter Property="ContentTemplate" Value="{StaticResource VM1Key}"/>
</DataTrigger>

<DataTemplate x:Key="VM1Key">
    <TextBlock Background="Green" Text="{Binding Name, Mode=OneWay}"/>
</DataTemplate>

So, in your case remove DataContext from your DataTemplate.

Upvotes: 0

Jai
Jai

Reputation: 8363

I am not very sure, but this should be how it should be done.

<DataTemplate x:Key="ManageTags" DataType="{x:Type vm:TagsEditViewModel}">
    <local:TagsEditView />
</DataTemplate>
<DataTemplate x:Key="ExportTags" DataType="{x:Type vm:TagsExportViewModel}">
    <local:TagsExportView />
</DataTemplate>
<DataTemplate x:Key="ImportTags" DataType="{x:Type vm:TagsImportViewModel}">
    <local:TagsImportView />
</DataTemplate>

This is what they call it "ViewModel-first-MVVM."

Personally, I've only used this for TabControl so I'm no expert on this either. Most of the time I'd just go "View-first-MVVM."

<local:TagsEditView>
    <local:TagsEditView.DataContext>
        <vm:TagsEditViewModel />
    </local:TagsEditView.DataContext>
</local:TagsEditView>
<local:TagsExportView>
    <local:TagsExportView.DataContext>
        <vm:TagsExportViewModel />
    </local:TagsExportView.DataContext>
</local:TagsExportView>
<local:TagsImportView>
    <local:TagsImportView.DataContext>
        <vm:TagsImportViewModel />
    </local:TagsImportView.DataContext>
</local:TagsImportView>

Upvotes: 0

David Meredith
David Meredith

Reputation: 446

For a ContentControl, you need to set the Content property, not the DataContext property. All of the child controls will then take their DataContext from the ContentControl's Content property.

Upvotes: 1

Related Questions