2
votes

I'm having an annoying issue that is not exactly causing problems, but it is generating a ton of binding errors unnecessarily.

I've basically tracked the problem down to the fact that setting the Content on a ContentControl changes the DataContext of its content before it applies the new ContentTemplate. Since the new Content is not of the same type as the old ContentTemplate expects, it generates binding errors from the old ContentTemplate.

Here's how I have the ContentControl set up. The Content is bound to the ViewModel for the selected tab, and the ContentTemplate is bound to the DataTemplate with the View for that tab. I used to have it using a ContentTemplateSelector instead of a converter with ContentTemplate, but that had the same issues so I tried this instead.

<ContentControl Content="{Binding SelectedTab, Converter={StaticResource ConfigurationViewModelConverter}}" ContentTemplate="{Binding SelectedTab, Converter={StaticResource ConfigurationTemplateConverter}}"/>

Perhaps I've got this wired up wrong somehow but everything is working perfectly with the exception of the binding errors I get when switching tabs, seemingly due to the Content and ContentTemplate getting briefly out of sync. Thanks in advance for any assistance.

1
I cannot reproduce the issue with ContentTemplateSelector. Can you provide an MCVE?Grx70

1 Answers

0
votes

So, I'm almost 2 years late on this, but I had been stuck on this exact same issue for about a day so I figured I'd share. I had 3 types of view models corresponding to 3 different UserControls/DataTemplates. I used a style to fix this

<ContentControl>
  <ContentControl.Resources>
    <DataTemplate x:Key="fooUc">
      <local:UC1 />
    </DataTemplate>
    <DataTemplate x:Key="barUc">
      <local:UC2 />
    </DataTemplate>
    <DataTemplate x:Key="bazUc">
      <local:UC3 />
    </DataTemplate>
  </ContentControl.Resources>
  <ContentControl.Style>
    <Style TargetType="ContentControl">
      <Style.Triggers>
        <!-- I'm assuming that SelectedTab is an int -->
        <DataTrigger Binding="{Binding SelectedTab}" Value="0">
          <Setter Property="Content" Value="{Binding FooVm}" />
          <Setter Property="ContentTemplate" Value="{DynamicResource fooUc}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding SelectedTab}" Value="1">
          <Setter Property="ContentTemplate" Value="{DynamicResource barUc}" />
          <Setter Property="Content" Value="{Binding BarVm}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding SelectedTab}" Value="2">
          <Setter Property="ContentTemplate" Value="{DynamicResource bazUc}" />
          <Setter Property="Content" Value="{Binding BazVm}" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ContentControl.Style>
</ContentControl>

The crucial thing to notice above is the ordering of my setters. If your view object must be changed before the view model object, then put it before, otherwise flip the ordering. The problem is that one has to be changed before the other, they can't change at the exact same time. If your controls are completely different from one another, then this will still produce errors (different ones though!). This worked for me because BarVm and BazVm have a subset of properties as FooVm.