What, No Design Mode Property?

Brian in Cider | 15 Comments July 3, 2006

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?


Comments (15) -

Ian Griffiths, Monday, July 3, 2006 at 10:54 AM

That code for retrieving the design mode flag is...surprising. Is that what everyone will need to write?
I think I'd prefer to have that wrapped in some sort of helper. I understand you don't want to have the runtime bits of the code have a dependency on the design-time libraries, but can't you just put that helper into PresentationFramework? Any argument along the lines of "It's design-time so it doesn't belong in there" seems inconsistent with the fact that you know people are going to need to do this in their runtime code. (After all, that's why this is an issue right?)
The reason I want it wrapped is that when I look at that, I think "Clunky and fragile". Clunky because it's an unpleasant (if short) piece of code. Fragile partly because it's relying on getting the right string, and partly because it screams "DEPENDS ON AN IMPLEMENTATION DETAIL OF THE CURRENT VERSION!!!". And OK, so you'd presumably commit to not changing it, and you'd document it so it's not technically an implementation detail. But it still has that feel to it.
And it also has me thinking "Who exactly is in charge of allocating names to AppDomain data items? "IsDesignModeProperty" is a fairly generic term. (Why not "IsWpfDesignModeProperty"? There are other frameworks that have design modes, surely? After all, the Workflow team appear to have their own entire parallel version of the DependencyProperty system...) Presumably you can't be sure that no other application already out there has every added an AppDomain prop with the same name. This adds to the impression that this is a fragile solution.
It'd just be so much nicer to have a little helper class that gives you access to the DP and its current value. That way, you don't get that little snippet of code duplicate a million times over. You don't have that "guts on show" feel because that AppDomain data lookup is now hidden inside a Microsoft-supplied class.
Anyway, I'll stop ranting now. In summary: please wrap it in something that looks nicer. Smile

Keith Hill, Monday, July 3, 2006 at 12:51 PM

+1 for everything Ian said.  Also false positives concern me a bit because I usually rely on DesignMode to "turn off" runtime functionality during design time.  If my runtime functionality was mistakenly turned off at runtime that wouldn't be good.  Yeah you mentioned catching OnPropertyChanged but it seems like "correct" runtime behavior shouldn't require that.  I guess I value correct runtime behavior over correct design time behavior.  

Brian, Monday, July 3, 2006 at 9:55 PM

Ian and Keith -- Thanks for the feedback.  Our intention is to eventually push this down into the framework, and we would maintain the late bound access technique for backwards compatibility.  We unfortunately can't add an API to this version of WPF because it is locked down and they are no longer accepting changes, so we are trying to find fairly a clean work around.  Granted, you have to put on your Mr. Magoo glasses to look at this and see it as "fairly clean", but it's the best solution we've come up with that doesn't require an external DLL dependency.
There will be a small, SP-level framework update when Orcas ships and we can try to add the property to that.  We don't want to require the SP for runtime code, however, so we can't get away from supporting some late bound sniff like I described.
Keith -- the property is only stored in the domain data when your control is running in a designer, so in an application there is no risk of it returning true.  The false positive risk comes from parts of the Visual Studio or Sparkle UI that are not part of the designer instantiating controls.  For both tools, the only place that can happen is in the property grid, and those controls are typically custom written to support the grid.
If we take that we can't add this property to WPF for this version as a given (which it is; I've tried smaller additions to WPF and been laughed out of the conference room), I'd like your input on other options.  We can:
1) Roll this code into a simple utility DLL that folks would have to redistribute.
2) Roll this code into our standard base SDK DLL.  Professional control developers wouldn't want to take a dependency on this and would use the late bound technique, but for in-house projects it might be OK.  Our base SDK DLL would then have to be redistributed with the control.
3) We could roll this into a utility class that we bundle as part of the VS project templates (or we could roll it into a snippet)
4) We could do this in a module that people could link in.  That's nice and clean in theory, but unfortunately the tool support for modules is really poor so I don't see this as a viable option.
Of these, #3 is my favorite.  We could also take that as an opportunity to make the data name more unique (I hate to use the term GUID here, but that's essentially what it is).
Do either of you (or anyone else) have a preference?  This is a good time for feedback because, while we can't change WPF, this feature is not yet in our code and is very easy to change.

Ian Griffiths, Tuesday, July 4, 2006 at 1:54 AM

When you say a module that people could "link in", this is not in the classic sense of old-style linking where it would be merged into the binary file right? Last time I used modules, adding in a module meant you ended up with an assembly consisting of multiple files - is that still the case with Orcas?
Assuming that's correct, I agree that 3 is the best option given the unfortunate constraints. Particularly if the goal in the long run is for this to be in the framework - adding a new DLL that needs to be redistributed just to provide what would be a temporary home seems messy. Unless, that is, this DLL would eventually become the vehicle by which this functionality eventually becomes part of the main WPF redist.
(E.g., you add a DLL called PresentationFramework.Design.RuntimeSupport.dll or something. In the Orcas timeframe, this is something that needs to be redistributed with your control if you use it. But in the future, it becomes part of WPF. That way the only thing that changes is who's responsible for distributing it.)
Even then, I think I'd prefer something where I can minimize the prereqs of my control component - if I can possibly package things in a single DLL file and have it work, then I'd prefer to do that. So 3 still looks preferable, and I'll just wait for the feature to be added to the framework in v.next...
As for naming of the data slot, I'd actually be happier if the thing was an actual GUID. Particularly if this is code that is going to provided by Microsoft (eventually in the framework, but initially in a template). That way I'm more confident it's not going to collide with anything else.

SeeR, Tuesday, July 4, 2006 at 5:20 AM

First of all I don't even installed WPF SDK on my machine, so my understanding of classes structure is taken from MSDN.
I don't know if you are using in WPF such thing like IServiceProvider, but I think that "dependency injection" is a "must be" thing so assume that you use it.
First create
interface IDesignModeInfo
  bool DesignMode
then all controls need to have constructor
public Control(IServiceProvider provider) : this()
  this.Provider = provider;
and property
public virtual bool DesignMode
    if(Provider == null) return false;
    IDesignModeInfo info = Provider.GetService(typeof(IDesignModeInfo)) as IDesignModeInfo;
    if(info == null) return false;
    return info.DesignMode;
Now all you need to do is to be sure that all controls are created by this new constructor and in design library implement interface IDesignModeInfo.
This is not complete solution, but you got the point - use ServiceProvider

Brian, Wednesday, July 5, 2006 at 10:25 AM

Ian -- Thanks.  The modules I'm talking about are the same multi-file assemblies you know about.  Not terribly convenient.  I'm going to write a proposal up today to do #3.  As for using a real guid, we'll use that as a fallback.  My preference would be to reach an agreement with the WPF team about what this property will be, and then use the full name of the property as the key.  For example, the key might be "System.Windows.Design.DesignTimeProperties.IsInDesignMode".  I think that's unique enough (hell, it's longer than a GUID).  I prefer it over a GUID because it links this late bound concept with the actual property it is exposing.
SeeR --
Unfortunately this won't work.  We need an assembly that introduces IDesignModeInfo, which puts us back where we are now with not having an assembly for it to live in.  Also, the service provider technique works fine if the designer creates all the controls, but for controls that are nested inside user controls it doesn't work because the runtime creates those controls.  If we could plumb this throughout the runtime so WPF itself knew to pass the service provider downward, you could do a lot with it at runtime too.  A better way to do this sort of thing in WPF is to use data binding, however, as data contexts inherit and can be declaratively associated with the UI.

SeeR, Wednesday, July 5, 2006 at 10:56 PM

1) In .NET 1.1/VS 2003, which I still use, I solved the problem of passing ServiceProvider by creating base class for all my controls
[RootDesignerSerializer(typeof(ServiceClientSerializer), typeof(CodeDomSerializer), true)]
public class ServiceClientUserControl : UserControl
ServiceClientSerializer is responsible for changing the body of InitilizeComponent() method in a such way
private void InitializeComponent()
  this.components = new MyContainer(this);
and here is simple code for MyContainer
public class MyContainer : System.ComponentModel.Container
  IComponent parentComponent;
  public MyContainer(IComponent parent)
    parentComponent = parent;
  protected override object GetService(Type serviceType)
    object service = base.GetService(serviceType);
    if(service == null)
      IServiceProvider provider = parentComponent as IServiceProvider;
      if(provider != null)
        service = provider.GetService(serviceType);
      else if(parentComponent.Site != null)
        service = parentComponent.Site.GetService(serviceType);
    return service;
So now all I have is to inherit from my ServiceClientUserControl and designer generates all code to pass ServiceProvider to controls and components on my UserControl. Of course all my UserControls must have constructor
public MyUserControl(System.ComponentModel.IContainer container)
but it's generated automatically by file template.
You are now defining the base classes for WPF (correct me if I'm wrong Smile, please introduce support for IServiceProvider and simple passing it down - it's worth more then it looks at first.
I don't get the whole idea with Container and Site, so you could do it by simple passing IServiceProvider or any other better way Smile
2) Why not put IDesignModeInfo into into the same assembly with UserControls. How this is different from your checking AppDomain property pointed by string? How it's different from creating DesignMode property in base UserControl class?
Some useful links:

Brian, Thursday, July 6, 2006 at 9:07 AM

SeeR --
Thanks for the clarification.  Yes, this is a really good way to plumb services all up and down your UI framework and it has many advantages.  In my opinion we made a huge mistake in Windows Forms by not having the siting mechanism inherit parent services.  It kills the applicability of services for most applications.
We are not actually in a position to make changes to the WPF base classes.  Asside from bug fixing, they're done and they are not accepting API changes any longer.  That's the challenge for us:  we cannot add new runtime features and we are constrained to use the types that already exist in WPF.
One cool thing about WPF is that you can do what you want with services very easily.  I can define an attached property that looks like this:
public static class ApplicationServices {
    public static readonly DependencyProperty ServiceProviderProperty = DependencyProperty.RegisterAttached(
        "ServiceProvider", typeof(IServiceProvider), typeof(ApplicationServices),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
    public static object GetService(DependencyObject d, Type serviceType) {
        IServiceProvider p = d.GetValue(ServiceProviderProperty) as IServiceProvider;
        if (p == null) return null;
        return p.GetService(serviceType);
The cool thing about this is any app can do it without any runtime changes.  By declaring the property as inherited, any control running in my application can get to a service provider.  With a few simple changes you could also modify the code to allow for a local service provider that provided some services and then delegated to a parent provider for the rest, just as you have shown.
It's cool that you're able to get the code generation in VS 2003 to emit your own container.  This technique is fantastic when you can get it to work with the designer.

Frank Hileman, Thursday, July 6, 2006 at 10:18 AM

Ideally DesignMode would not be a boolean. It would have three states:
- TopLevelDesign -- a top-level component in design mode
- NestedDesign -- a top-level component is using this child component more like a run-time component, but we are still running in a designer
- RunTime
With these three states developers could tailor behavior differently depending on the situation. For a nested component, behaving as a run-time component is not right, but behaving as a top-level designed component is not always right either.
To implement that correctly would require some kind of semi-global state (state from the top, indicating design mode at the top-most level), as well as local information. How it is implemented, I don't care, but one thing I have noticed: people often do not want a real separation between design-mode code and run-time mode code -- they want to be able to switch at any time. Omitting design time features completely from the run time API just makes life harder.

SeeR, Friday, July 7, 2006 at 2:14 AM

Ahh right, i should read your post more carefully about your separation from WPF.
I give up Smile I know to few about WPF to help you.
But on your place I would look for some solution connected with IServiceProvider to allow selectively manage which control have DesignMode = true and which false.

Brian, Tuesday, July 11, 2006 at 8:42 AM

Frank --
What are the scenarios where you want to discern the top level element from children?  Cider works a little differently from the component model architecture in that there is no "root" designer, so none of our code needs any kind of mode switch.

Gary E, Tuesday, July 11, 2006 at 8:56 PM

Hi Brian,
I just found your blog and I think you have some great information here.  I look forward to keeping up with the progress of Cider.
It's a little off topic from your current post but I was hoping you could help answer a question for me regarding the Cider Designer.  With .NET 2.0 and the Windows Forms designer, it is pretty easy to host the designer in a 3rd party application by using the DesignSurface class.  Will this sort of functionality exist with the Cider designer?  i.e. Is it possible and permissible to host it in an application?  The WPF product we are developing needs to allow end users to modify & create custom forms and it would be great to leverage the functionality built into Cider.
Gary E

Brian, Tuesday, July 11, 2006 at 10:44 PM

Gary -- Welcome aboard.  Your question isn't off topic at all.
For V1 of Cider I'm afraid to say that it won't be possible to re-host it in a 3rd party application.  Supporting that is definitely something we're very passionate about, and we are absolutely architected in such a way to support it.  However, we simply don't have the time to expose the hosting APIs publicly and get them properly documented and tested for the wide range of scenarios we would need to support.  
I actually have a sample that allows you to host Cider in an application using the June CTP, but I did not post it.  We will make the hosting interfaces internal before we ship so we don't paint ourselves into a corner, and posting the sample seems like a slap in the face.
That said, Cider really does have a dual personality.  On the one hand, it is an SDK for building designers based on WPF.  On the other hand it is a designer for WPF that is built out of that SDK.  You can certainly take the SDK and use it elsewhere.  While it is more work than what DesignSurface requires because you start with no designer features, the SDK makes it far easier to create a designer than it would be if you started from scratch.  It is way too early to make any claims as to what will and will not be in the final SDK, but there should be plenty in there to give you an enormous head start.

Gary E, Thursday, July 13, 2006 at 4:08 PM

Thanks for your quick response.  It wasn't quite the answer I was hoping for but at least it gives me a clear direction.  I certainly understand the time constraints you must have.  I'll start digging into the SDK side of Cider and start thinking about what it will take for me to build a designer on top of it.  Any suggestions or samples would be appreciated.
Thanks Again,

Richard Houltz, Thursday, August 3, 2006 at 3:28 AM

I too need to make a WPF designer available in our software. We are using the Windows Forms 2.0 designer today. Now we have made our own designer for WPF out of several a few existing samples and our own explorations. It is not very generic though since we only need to use the Canvas panel. A part from that it works quite well, but it will get harder when we have to support third-party controls and their design-time features. I would very much like to check your sample out that hosts the Cider designer so please (pretty please, with sugar on top....) post that code or at least send it to me (and perhaps Gary.. Smile. BTW, your blog is a goldmine for us!!
Comments are closed