Search code examples
c#wpfxamlmvvmdatacontext

View model doesn't get updated to DataContext


I have a working program where the view model feed the data to the view. This is done in the constructor and also in a Refresh() method, as shown below. I usually put a private property referring to the view model because I want to omit casting when communicating with it.

public class TheView
{
  private ViewModel TheViewModel { get; set; }

  public TheView()
  {
    TheViewModel = new ViewModel();
    DataContext = TheViewModel;
  }

  public Refresh()
  {
    TheViewModel = new ViewModel();
    DataContext = TheViewModel;
  }
}

Then, I got gready and started chasing lines. Since the constructor connects DataContext to the property TheViewModel, I figured I could just assign to the latter and the former would get it's stuff updated by itself. To my disappointment, I discovered that it wasn't so. The following get me the correct list of objects but the DataContext stays unaffected.

public class TheView
{
  private ViewModel TheViewModel { get; set; }

  public TheView()
  {
    TheViewModel = new ViewModel();
    DataContext = TheViewModel;
  }

  public Refresh() { TheViewModel = new ViewModel(); }
}

The question is why it is so. Or rather, if it's supposed to be so. I'm thinking, in case it isn't supposed to behave like this, perhaps I have issues elsewhere in the code that poofs the flow...


Solution

  • I think you do need understand that DataContext is a dependency property.

    Its definition looks like this:

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Localizability(LocalizationCategory.NeverLocalize)]
    public object DataContext
    {
      get
      {
        return this.GetValue(FrameworkElement.DataContextProperty);
      }
      set
      {
        this.SetValue(FrameworkElement.DataContextProperty, value);
      }
    }
    

    ...

        public static readonly DependencyProperty DataContextProperty = 
    DependencyProperty.Register("DataContext", typeof (object...
    

    Dependency properties are more than normal .NET properties because they support

    • change notification
    • property value inheritance
    • providers which determine the value

    In your case it is the "change notification" topic which is important.

    When you (re-) assign a value to a property which is a dependency property (like DataContext) then WPF will pick up this change automatically. In this case the change notifcation is done inside the setter of the dependency property so to speak.

    If you assign to a "normal" property or even a private field this is not the case (the setter of the DataContext property is not invoked) even if it points to a DataContext.