WPF: Tips - Designer Detection
Occasionally you will have a piece of code which runs fine when you f5 but when you open the Window or Usercontrol you get a spurious error.
This tip offers a simple way to make that error go away.
Another use of this tip is when you want to mock some data for your View but it doesn't suit designer data for whatever reason.
Avoiding Errors
When you work on a WIndow/UserControl in the designer it "runs" the parameterless constructor.
If you have code in there which is reliant on something usually provided by some other piece of code then this often causes a problem.
The designer doesn't run any other code first so dependencies usually provided elsewhere can be missing and cause errors.
Suppressing these is a matter of detecting whether that code is running in the designer or not.
It's often most convenient to just return out the constructor:
public MainWindow()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
return;
// Dependent code which produces errors
}
Note that you can alternatively use "this" in the above code instead of newing up a DependencyObject. The Window itself inherits from DependencyObject.
The more complicated version is there in case you wanted to put it in a viewmodel or something.
Also.
One reason you get such errors is because you're doing something a bit dodgy like when you're working on a usercontrol attaching an event to some parent window you're expecting to be there. It won't be in the designer when you open that usercontrol and in that case you should perhaps consider a different ( less dodgy ) approach or null check.
Try and avoid dependencies which won't be resolved by merged resources.
Mocking
It's usually totally impractical to have the designer make a database call and without that you can't see data in your controls. This can make designing rather tricky as you need to fire the thing up in order to see what it will really look like.
Designer data context is the first option to consider but this can be unattractive - you're swapping the viewmodel which can mean duplicated code or introducing another degree of separation you don't want.
You can of course use IoC frameworks to do all sorts of complicated switching of resources but a simple approach is to have a constructor of a ViewModel which takes a parameter and injects it into an internal collection rather than reading data from a database.
This is also a lot easier to explain without a full blown sample project ;^)
public MainWindow()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this))
{
XDocument doc = XDocument.Load("Customers.xml");
this.DataContext = new MainWindowViewModel(XdocToList(doc));
}
else
{
this.DataContext = new MainWindowViewModel();
}
This is intended more to give a flavour of the approach rather than an in depth explanation.
Here an xml file is read off disc and manipulated by a helper method. Let's gloss over the details of that but it'll grab the data and iterate the nodes newing up Customer objects.
In this way a suitable list is passed into one constructor of the viewmodel.
The usual parameterless constructor of the viewmodel with no list will make an asynchronous call to read the data from a database instead.
See Also
This article is part of the WPF Tips Series, if WPF is your area of interest then you will probably find other useful articles there.