UserControls are not getting DataContext set to their ViewModel in 3.2

Topics: Questions
Jul 18, 2012 at 6:59 PM
Edited Jul 18, 2012 at 8:11 PM

EDIT:  This topic may be moot.  I just realized that the content of  my UserControl IS getting its DataContext set to the ViewModel.  The UserControl itself is not.  I assume this is by design?  

 

I am probably missing something simple, but I have been struggling for 2 days to figure this out:

I am pretty sure this started when I upgraded to using Catel 3.1 or 3.2 from 2.x.  

None of my UserControls are having their DataContext set to their ViewModel.  The ViewModel is created, but never assigned to the control's DataContext property.  This is true whether I derive from Catel's UserControl or use logic in behavior.  

The UserControls are just inheriting their DataContext from their parent objects, which is default WPF behavior.  

In poking around the 3.2 source code, I don't see anywhere that UserControlLogic sets the DataContext.  There is a method, UpdateDataContextToUseViewModel, but that method doesn't actually set the DataContext, it just creates the ViewModel.  The only two places where I see that the DataContext is set to the ViewModel are both in LogicBase - one is in the constructor, and one is in OnTargetControlLoaded.  UserControlLogic overrides this method, but does not call the base method or explicitly set the DataContext.  

Here is an example of how one of my UserControls is declared:

XAML:

 

<catel:UserControl x:Class="MyApp.Views.UserControls.StripTemplateControlEntry"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:catel="http://catel.codeplex.com"
                 xmlns:vm="clr-namespace:MyApp.ViewModels"
                   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                   mc:Ignorable="d"
                   d:DataContext="{d:DesignInstance Type=vm:StripTemplateControlDesignViewModel, IsDesignTimeCreatable=True}">

<UserControl.Resources>
...
</UserControl.Resources>

<!-- Content -->

</catel:UserControl>

 

Code Behind:

 

public partial class StripTemplateControlEntry : Catel.Windows.Controls.UserControl
 {
public StripTemplateControlEntry()
            : base()
        {
            InitializeComponent();
        }

protected override Type GetViewModelType()
{
      return typeof(StripTemplateControlEntryViewModel);
}
}

Note that in this case, I need to override GetViewModelType() because my control has 'Control' in the middle of the name, which confuses the ViewModel name resolution.



It's hard to imagine this could be a bug in 3.x or others would have run into it, but what am I doing wrong?

Coordinator
Jul 19, 2012 at 8:55 AM

Yes, this is by design.

What internally happens is that the content of the user control is replaced by a grid that gets the datacontext set as view model. In the old days (pre 3.0), we actually replaced the UC datacontext, but this was extremely complex and we had to work around a lot of issues in WPF and SL.

You can get the view model by casting the IView and retrieving the ViewModel.