Quantcast
Channel: Pocket Silicon - Cider
Viewing all articles
Browse latest Browse all 20

What, No Design Mode Property?

$
0
0

If you’ve written controls for Windows Forms you may have encountered a property on the control called DesignMode. This property returns false when the control is running in an application and true when the control is running in a designer. I’ve always considered this property to be a necessary evil. On one hand, we did a lot of work in Windows Forms to allow you to separate your design time logic into a separate DLL from your runtime logic, so the property is unnecessary. On the other hand, it just isn’t always practical or possible to separate all design time logic out of your runtime DLL.

Unfortunately, the DesignMode property in WindowsForms has some flaws. It is only set in response to a control getting its site property set by the designer. That property is set after the control is created, which often happens much later than control developers want. Worse is that it is only set on controls that are part of the design surface. If you had a control that was embedded inside of a user control, the user control’s DesignMode property gets set to true while your control’s DesignMode property stays set to false.

We wanted to solve this for WPF and Cider, and it is a surprisingly sticky problem.

The first challenge for us was to find a way for control vendors to even find the design mode property! No WPF classes have a DesignMode property. No problem, you can just use an attached property, right? Well, not quite. We are shipping the design time SDK for WPF separately from the WPF runtime so we can add new features to the design time independently of the runtime. If we defined an attached property there, you’d have to take a dependency on the design time assembly in your runtime control, and then redistribute that assembly with your control. We don’t want that.

Our solution to this is to allow you to lookup the property by name through the app domain data context. The code in WPF to get to the design mode property looks like this:

private bool IsDesignMode {
get {
DependencyProperty isDesignModeProperty = (DependencyProperty)AppDomain.CurrentDomain.GetData(“IsDesignModeProperty”);
return isDesignModeProperty == null ? false : true.Equals(isDesignModeProperty.GetValue(this));
}
}

When both Cider and Sparkle start, they define this property and set it into the app domain’s data context, so it will be available from your control’s constructor.

The next thing we wanted to solve was the nested control problem. Remember that in Windows Forms a control nested in a user control never has its design mode property set to true. This was an issue for many people. Our solution to this is to reverse the defaults on this property. Let’s look at the registration of this dependency property:

private static readonly DependencyProperty IsDesignModeProperty = DependencyProperty.RegisterAttached(
“IsDesignMode”, typeof(bool), typeof(DesignerView),
New FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));

There are two interesting parameters we’re passing. First, notice that the default value of the property is true. We decided it was much more reliable to make control default to being in design mode and then later set it to false if we need to. Second, notice that we’ve marked the property as inherited so that it will inherit up the UI hierarchy. This way nested controls still receive the correct value.

When you put it all together the result is that the DesignMode property is always available when you're running in Visual Studio or Sparkle but sometimes it will give you false positives. For example, if your control is hosted inside the property window, it will report that it is in design mode until it is parented to the property window. Normally this will only be an issue for a control if it does some sort of “mode switch” up front. If that is the case you can always override OnPropertyChanged on your control to see if the property value gets updated.

What do you think? Is this a good way to get to the design mode bit for Cider and Sparkle?

 


Viewing all articles
Browse latest Browse all 20

Trending Articles