Designer Hosting in Whidbey


If you have had a chance to play with Visual Studio Whidbey, you may have noticed some of the cool new features in the Forms designer – snap lines, smart tags and so on. Now what if you desire to expose some of this design time UI in your own application? Guess what, Whidbey makes this super easy to do! As I will show below, with less than 10 lines of code, you can display a form that hosts the Windows Forms designer.


The designer classes you will need are located in the various System.*.Design namespaces, particularly System.ComponentModel.Design. These are part of System.Design.dll, so you will first need to add a reference to this assembly (that ships as part of the .NET Framework SDK).


The first thing you need to do is create a DesignSurface. This is the class that represents the user interface that you would think of as the “designer”.



DesignSurface surface = new DesignSurface();


There, now we have a DesignSurface. Next, we need to indicate what the type of the root component is, and ask the DesignSurface to load it. We want a Form designer, so:



surface.BeginLoad(typeof(Form));


BeginLoad begins the process of loading the designer, and will continue asynchronously. However, the “view” that represents the root component at design time is immediately available after this call.



Control view = (Control) surface.View;


Cool, now we have a Control that represents the View. We can manipulate this Control just like any other Windows Forms Control. In this case, lets dock fill it and add it to a Form.



view.Dock = DockStyle.Fill;
Form myDesigner = new Form();
myDesigner.Controls.Add(view);
myDesigner.Show();


That’s it! You now have a form hosting the Windows Forms designer, complete with support for snap lines, smart tags etc! Ofcourse, to create a little more functional designer, you need to provide a way to add components to the Form, set properties etc. You may also need to implement a couple of designer services along the way. But the 7 lines of code above are all you need to get started!

Comments (26)

  1. This is very interesting! What about support for alternative forms of serialization? I have heard the CodeDom serializer will become available outside of VS in Whidbey. This should make it possible to do undo/redo, correct?

    But is there any support for alternative serialization formats. It seems that anything that can save and restore property values and object graphs might be hooked into a generic framework, if this has been addressed. For example, an xml format such as MyXaml.

  2. I forwarded your question to our designer guru, Brian Pepin, and here is what he said:

    "Yes, we’re still using the code dom. It is supported to serialize designers using any format you like, but integrating this into VS takes work and access to the VSIP program. Frank’s MyXaml should work fine, and should even work with undo / redo provided he implements a ComponentSerializationService based on MyXaml."

  3. This is great, just need some more information on how to implement the service and integrate in VS. I could find almost no information. We are in the VSIP, but I was hoping a package would not be necesary, simply because packages are very user-unfriendly for installation/uninstallation. Plus we prefer to use managed code as much as possible.

  4. Peter Meyer says:

    From the entry above:

    "Of course, to create a little more functional designer, you need to provide a way to add components to the Form, set properties etc. You may also need to implement a couple of designer services along the way."

    Is there any more documentation or samples on the little details mentioned above?

  5. Frank/Peter: I don’t know if there is any documentation already available, but I do know folks in my team are writing some cool samples that will soon be published on http://windowsforms.net. Hopefully, those will help you get started.

  6. Peter Meyer says:

    Thank you very much! Can’t wait to see those samples 🙂

  7. David Snipp says:

    Can you give any more information on those samples ?

    In particular, I’ve managed to integrate a designer into our application, but Whidbey appears to generate Code that fails to compile as soon as you have a property that refers to a resource.

    As there is so little documentation available, I don’t know if it’s me or a bug in Beta 1.

  8. David: Can you please report your problem through the MSDN Product Feedback site (http://lab.msdn.microsoft.com/productfeedback/)? That would help us investigate further.

  9. xzw says:

    but, i want to hosting web form, just like ASP.NET web Matirx, if i can use the class DesignSurface, how to do it ?

  10. rprabhu says:

    xzw: I suggest contacting Nikhil (http://www.nikhilk.net/) or Bradley (http://blogs.msdn.com/bradleyb/default.aspx) and they should be able to point you in the right direction.

  11. Frederik says:

    Let’s see if you still read these comments ;).

    I have a Form that I loaded using a custom serialization process with a bunch of controls on it, something like

    Form from = MySerializer.Load(myFile);

    now I want to show this form in the designer and have ALL it’s controls in ‘design mode’, etc that the user can move it around, edit it,…

    I tried doing it like this:

    IContainer container = DesignSurface.ComponentContainer;

    // (snip)remove everything

    container.Add(form);

    but that way, only the form itself and not the controls on it can be designed. What am I doing wrong?

    Frederik.

  12. rprabhu says:

    Frederik: Yes, I see comments since I get email notifications for them 🙂

    Regarding your question: you need to walk the controls and site each of them in the designer (by adding them to the DesignerHost). That way, all the controls will be in design mode and not just the form.

    BTW, you might want to check out Mike Harsh’s ‘Design Mode Dialog’ sample that does something like this. Its up on the samples page on windowsforms.net:

    http://windowsforms.net/Default.aspx?tabindex=4&tabid=49

  13. Frederik says:

    Yup, I found out about that sample shortly after posting my previous message. After updating it a little but so it would work on Beta 2 and making sure that *all* possible properties would get copied (I don’t see why the sample limits that scope), I put all the funtionality in a class.

    I’m, right now, seeing something quite weird. When I load a form and copy the controls, they show up in design mode indeed. However, *clicking* on the controls will not select them! If I make a selection around them with my mouse (eg. left click left of the control, keep the mouse button down and then select the control), they get selected.

    Does it sound familiar? Am I missing something obvious or did I just hit a bug that should get logged through ProductFeedback?

  14. Frederik says:

    Okay, I figured out that blindly copying all properties won’t work, since that will copy, for example, the Site property etc, things that the designer will set. Or at least, that’s what I think (I’m not really into design-time experiences).

    I switched back to copying only a select set of properties and tadaa… it works :).

    The fact that you have to recursely copy all controls to the to be designed form should, in my opinion, *really* be mentioned on the MSDN docs…

  15. rprabhu says:

    Glad you got it working. I agree the behavior is non-obvious. We are working on having a more detailed sample and whitepaper up on MSDN on this topic by the end of this summer. That should serve as a good starting point for folks doing this sort of thing.

  16. Frederik says:

    Okay, I’m back and I’m seeing some really weird behaviour again.

    I am still trying to show controls in the designer. As a backgrounder, I am trying to design Windows Installer dialogs as defined in WiX source code.

    For every control that MSI supports, I added a new WinForms control in my DLL. For example, ‘PushButton’, that just inherits from Button.

    Every control as an Element property that will hold the source code that defined the control, so that I can track where the control that is being shown in the designer, is defined in the souce code.

    I create a new form and add all the required controls on it, set the Element property and so on. My dialog displays well and I get more or less what I expected.

    When I copy the form and the controls to the designer without copying the Element property (well, only copying a select set of properties), it all works well.

    Once I do copy the Element property, the form still displays in the designer, but I can’t select a control by clicking on it and ‘weird’ things seem to be happening.

    Setting the Element property does more than just assigning a value to a field, to be exact, it also sets the Size and Location properties.

    Do you have any clue as to what could be going on here? I can send you the source code that reproduces the behaviour, or submit a bug on ProductFeedback or whatever. I really have no clue what I’m doing wrong here…

    All I can say is that it’s weird, very weird and smells like a bug 🙂

  17. rprabhu says:

    Hmm – can’t say off the top of my head what the problem might be. Perhaps an exception is thrown at some point when setting the Element property and that leaves things in a bad state?

    I would try catching all exceptions and seeing if there are any stray ones.

    If you can’t get to the bottom of it, please report the problem through Product Feedback (with the project attached that reproduces the issue) and we can try to help.

  18. kurt says:

    Cool stuff, quick question:

    You Said:

    Regarding your question: you need to walk the controls and site each of them in the designer (by adding them to the DesignerHost). That way, all the controls will be in design mode and not just the form.

    My question:

    Can you give a couple of lines of code showing this?

    Thanks!

  19. rprabhu says:

    Mike Harsh’s ‘Design Mode Dialog’ sample that I linked to above has the code that does this.

  20. jeff says:

    I’m trying to figure out how to hook into the code that handles drawing the control as it is being dragged.  I have an overlay control that is mostly transparent and is placed over the top of a background image.  It works great in design mode, but when I start to drag it, something is taking a snapshot of the current state of the control and using that as the picture as it is being dragged around.  So in effect, it looks like I’m moving a portion of my background image around the screen when I move my control (once I drop it, the control refreshes and becomes transparent again).  Ideally, I would like to simply draw a rectangle that represents the location of the control as it is being moved around, preserving transparency inside the control and leaving the background image alone.  Any idea how I might be able to override this behavior?  

  21. rprabhu says:

    I forwarded your question to Martin Thorsen, who has a good knowledge of the drag/drop implementation. Here is what he had to say:

    "The only way for him to do this is to handle the WM_PRINT command. Preferably he should do that in his control designer’s wndproc. When we generate the drag image, we send a WM_PRINT to the control."

    If you have further questions on this, you may want to post them on the WinForms Designer forum, where you should hopefully get a quick answer:

    http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=5&SiteID=1

  22. Gary says:

    This is great but I’m working on a WPF project.  Is there any support for this using the Cider (or other XAML) designer?

  23. rprabhu says:

    Gary: Sorry, I don’t know, but you can contact one of the Cider bloggers listed here or ask on their forum: http://wpf.netfx3.com/content/cider.aspx