Search code examples
wpfmvvmdatatemplatedatacontext

Binding usercontrols Datacontext in DataTemplate


I have two usercontrols inside of a TabItem. The TabItem has it's own ViewModel, which has a property that the TabItem's child ContentControl's content bound to. This property represents another viewmodel, which will change the view depending on which one it is. Here's an example:

<TabItem DataContext="{Binding Path=MainLayerTabViewModel, Source={StaticResource ViewModelLocator}}" Header="Layers">
    <ContentControl Content="{Binding ChildViewModel}">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type vm:LayersViewModel}">
                <views:LayersTabView DataContext="{Binding ChildViewModel}"/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type vm:UserDrawnLayersViewModel}">
                <views:AlternateLayersTabView DataContext="{Binding ChildViewModel}" />
            </DataTemplate>
        </ContentControl.Resources>
    </ContentControl>

Here's the view model used as the datacontext for the tabitem:

public class MainLayerTabViewModel : ViewModelBase
{
    public object ChildViewModel { get; set; }

    public MainLayerTabViewModel()
    {
        ChildViewModel = (App.Current.Resources["ViewModelLocator"] as ViewModelLocator).LayersViewModel;
    }
}

Now, the two types of possible ViewModels for the ChildViewModel are LayersViewModel and UserDrawnLayersViewModel. When I change ChildViewModel to one of those, the view is properly switched via the DataTemplate. But the DataContext isn't actually being set. Nothing is being bound. I tried creating separate properties for each ViewModel in the MainLayerTabViewModel and binding the DataContext of each view to its own property, but that didn't work either.


Solution

  • I haven't verified this, however I can see couple of issue with your code.

    View should be

    <ContentControl Content="{Binding ChildViewModel}">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type vm:LayersViewModel}">
                <views:LayersTabView/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type vm:UserDrawnLayersViewModel}">
                <views:AlternateLayersTabView/>
            </DataTemplate>
        </ContentControl.Resources>
    </ContentControl>
    

    ViewModel:

    public class MainLayerTabViewModel : ViewModelBase
    {
        public ViewModelBase ChildViewModel { get; set; }
    
        public MainLayerTabViewModel()
        {
            ChildViewModel = new LayersViewModel();
            //or ChildViewModel = new UserDrawnLayersViewModel();
        }
    }
    

    Hope that helps..