3

I have Resharper on my Visual Studio, so setting the DataContext in a WPF xaml file is very useful to get to the IntelliSense. Something like this:

<UserControl ... blah blah namespace stuff >
  <UserControl.DataContext>
    <viewModels:FooViewModel />
  </UserControl.DataContext>

  <Label Text={Binding SomeText} /> <!-- I can get IntelliSense for SomeText -->
  ...

However, I want to do a bit of initialisation on the ViewModel/DataContext before I give it to the view. Something like this:

public class FooViewModel : INotifyPropertyChanged {
  private Foo Model { get; set; }
  public FooViewModel(Foo model) {
    Model = model;
  }

  // Only here for WPF compatibility - I realise this might be the root of my problems :)
  public FooViewModel() 
    : this (new Foo) {
  }

  public string SomeText { ... }
  ...
}

public class ShowFooer {
  public void ShowFoo() {
    Foo model = ... // get the foo from where ever
    FooViewModel viewModel = new FooViewModel(model);
    FooWindow window = new FooWindow(viewModel); // Push the data context into the constructor

    view.Show();
    ...
  }
}

When I debug through this I find that 2 FooViewModels are created - one where I push the context into the constructor, and one that is automatically created in the InitialiseComponents of the FooWindow.

tl;dr: Is there a way to say to WPF that I already have a data context and that I am just using the data context xaml tag to get IntelliSense? Is there a way from stopping it creating a new context? At the moment I am just commenting out the data context lines when I compile and uncomment them when I am coding.

Or alternative question: Is there a way to set the data context after the constructor, but have all the fields initialised from the second data context without having to do a long list of OnPropertyChanged calls?

Jonny
  • 2,509
  • 23
  • 42

2 Answers2

7

Yes. You can use this:

<UserControl
xmlns:viewModels="clr-namespace:..."
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 viewModels:FooViewModel, 
IsDesignTimeCreatable=True}" ...> ...

With this you get autocompletion for all vm properties.

A.B.
  • 2,374
  • 3
  • 24
  • 40
  • Works great thanks (after I did this fix too: http://stackoverflow.com/questions/8303803/setting-design-time-datacontext-on-a-window-is-giving-a-compiler-error) – Jonny Dec 07 '16 at 16:43
  • 1
    @Jonny: I'm glad, I could help you. Can you mark it then as answer please ? I added the missing part too. – A.B. Dec 07 '16 at 17:21
  • For autocompletion purposes, it doesn't matter whether `IsDesignTimeCreatable` is `True` or `False`. But it does matter to the design view. – Petter Hesselberg Dec 08 '16 at 17:06
1

The following XAML markup will cause an instance of the view model to get created at runtime using the default parameterless constructor:

<UserControl.DataContext>
  <viewModels:FooViewModel />
</UserControl.DataContext>

So you should remove this piece of markup (and probably also the default constructor) if you construct the view model yourself programmatically using the other overload that takes a model parameter.

You can then set a design time data context as suggested by Schwammkopf to get intellisense in Visual Studio.

mm8
  • 163,881
  • 10
  • 57
  • 88