title: UserControls and viewmodels in View-First-MVVM
body: <p>I'm forced to use View First MVVM in a WPF application and I'm struggling to see how it can be made to work elegantly.</p>
  
  <p>The root of the problem lies with nested <code>UserControls</code>. In an MVVM architecture each <code>UserControl</code> needs to have its view model assigned to its <code>DataContext</code>, this keeps the binding expressions simple, and what's more this is also the way WPF will instantiate any view generated via a <code>DataTemplate</code>.</p>
  
  <p>But if a child <code>UserControl</code> has dependency properties which the parent needs to bind to its own viewmodel then the fact that the child <code>UserControl</code> has its <code>DataContext</code> set to its own viewmodel means that an 'implicit path' binding in the parent XAML file will resolve to the child's viewmodel instead of the parent's.</p>
  
  <p>To work around this every parent of every <code>UserControl</code> in the application will either need to use explicit named bindings for everything by default (which is verbose, ugly and errorprone), or it will have to know whether a specific control has its <code>DataContext</code> set to its own viewmodel or not and use the appropriate binding syntax, (which is equally errorprone, and a major violation of basic encapsulation).</p>
  
  <p>After days of research I haven't come across a single half decent solution to this issue. The closest thing to a solution I've come across is setting the <code>UserControl's</code> viewmodel to an inner element of the <code>UserControl</code> (the topmost <code>Grid</code> or whatever), which still leaves you facing a problem trying to bind properties of the <code>UserControl</code> itself to its own viewmodel! (<code>ElementName</code> binding won't work in this case because the binding would be declared before the named element with the viewmodel assigned to its <code>DataContext</code>).</p>
  
  <p>I suspect that the reason not many other people run into this it that they are either using viewmodel first MVVM which doesn't have this issue, or they are using view first MVVM in conjunction with a dependency injection implementation that amelliorates this issue.</p>
  
  <p>Does anyone have a clean solution for this please?</p>
  
  <p>UPDATE:</p>
  
  <p>Sample code as requested.</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;!-- MainWindow.xaml --&gt;
  &lt;Window x:Class="UiInteraction.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="clr-namespace:UiInteraction"
          Title="MainWindow" Height="350" Width="525"
          x:Name="_this"&gt;
  
      &lt;Window.DataContext&gt;
          &lt;local:MainWindowVm/&gt;
      &lt;/Window.DataContext&gt;
  
      &lt;StackPanel&gt;
          &lt;local:UserControl6 Text="{Binding MainWindowVmString1}"/&gt;  
      &lt;/StackPanel&gt;
  
  &lt;/Window&gt;
  </code></pre>
  
  <pre class="lang-cs prettyprint-override"><code>namespace UiInteraction
  {
      // MainWindow viewmodel.
      class MainWindowVm
      {
          public string MainWindowVmString1
          {
              get { return "MainWindowVm.String1"; }
          }
      }
  }
  </code></pre>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;!-- UserControl6.xaml --&gt;
  &lt;UserControl x:Class="UiInteraction.UserControl6" x:Name="_this"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                xmlns:local="clr-namespace:UiInteraction"&gt;
  
      &lt;UserControl.DataContext&gt;
          &lt;local:UserControl6Vm/&gt;
      &lt;/UserControl.DataContext&gt;
  
      &lt;StackPanel&gt;
          &lt;!-- Is bound to this UserControl's own viewmodel. --&gt;
          &lt;TextBlock Text="{Binding UserControlVmString1}"/&gt;
  
          &lt;!-- Has its value set by the UserControl's parent via dependency property. --&gt;
          &lt;TextBlock Text="{Binding Text, ElementName=_this}"/&gt;
      &lt;/StackPanel&gt;
  
  &lt;/UserControl&gt;
  </code></pre>
  
  <pre class="lang-cs prettyprint-override"><code>namespace UiInteraction
  {
      using System.Windows;
      using System.Windows.Controls;
  
      // UserControl code behind declares DependencyProperty for parent to bind to.
      public partial class UserControl6 : UserControl
      {
          public UserControl6()
          {
              InitializeComponent();
          }
  
          public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
              "Text", typeof(string), typeof(UserControl6));
  
          public string Text
          {
              get { return (string)GetValue(TextProperty); }
              set { SetValue(TextProperty, value); }
          }
      }
  }
  </code></pre>
  
  <pre class="lang-cs prettyprint-override"><code>namespace UiInteraction
  {
      // UserControl's viewmodel.
      class UserControl6Vm
      {
          public string UserControlVmString1
          {
              get { return "UserControl6Vm.String1"; }
          }
      }
  }
  </code></pre>
  
  <p>This results in:</p>
  
  <blockquote>
    <p>System.Windows.Data Error: 40 : BindingExpression path error:
    'MainWindowVmString1' property not found on 'object' ''UserControl6Vm'
    (HashCode=44204140)'. BindingExpression:Path=MainWindowVmString1;
    DataItem='UserControl6Vm' (HashCode=44204140); target element is
    'UserControl6' (Name='_this'); target property is 'Text' (type
    'String')</p>
  </blockquote>
  
  <p>because in <code>MainWindow.xaml</code> the declaration <code>&lt;local:UserControl6 Text="{Binding MainWindowVmString1}"/&gt;</code> is attempting to resolve <code>MainWindowVmString1</code> on <code>UserControl6Vm</code>.</p>
  
  <p>In <code>UserControl6.xaml</code> commenting out the declaration of the <code>DataContext</code> and the first <code>TextBlock</code> the code will work, but the <code>UserControl</code> needs a <code>DataContext</code>. In <code>MainWIndow1</code> using an <code>ElementName</code> instead of an implict path binding will also work, but in order to use the <code>ElementName</code> binding syntax you would either have to know that the <code>UserControl</code> assigns its viewmodel to its <code>DataContext</code> (encapsulation failure) or altenatively adopt a policy of using <code>ElementName</code> bindings <em>everywhere</em>. Neither of which is appealing.</p>