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

  • Anonymous
    June 14, 2004
    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.

  • Anonymous
    June 15, 2004
    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."

  • Anonymous
    July 03, 2004
    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.

  • Anonymous
    July 07, 2004
    The comment has been removed

  • Anonymous
    July 08, 2004
    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.

  • Anonymous
    July 08, 2004
    Thank you very much! Can't wait to see those samples :-)

  • Anonymous
    July 24, 2004
    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.

  • Anonymous
    July 26, 2004
    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.

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

  • Anonymous
    July 18, 2005
    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.

  • Anonymous
    July 19, 2005
    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.

  • Anonymous
    July 19, 2005
    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

  • Anonymous
    July 20, 2005
    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?

  • Anonymous
    July 20, 2005
    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...

  • Anonymous
    July 20, 2005
    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.

  • Anonymous
    July 26, 2005
    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 :)

  • Anonymous
    July 27, 2005
    The comment has been removed

  • Anonymous
    September 01, 2005
    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!

  • Anonymous
    September 09, 2005
    Mike Harsh's 'Design Mode Dialog' sample that I linked to above has the code that does this.

  • Anonymous
    April 20, 2006
    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?  

  • Anonymous
    April 21, 2006
    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

  • Anonymous
    July 11, 2006
    This is great but I'm working on a WPF project.  Is there any support for this using the Cider (or other XAML) designer?

  • Anonymous
    July 11, 2006
    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

  • Anonymous
    May 29, 2009
    PingBack from http://paidsurveyshub.info/story.php?title=cool-client-stuff-designer-hosting-in-whidbey

  • Anonymous
    June 08, 2009
    PingBack from http://insomniacuresite.info/story.php?id=4175

  • Anonymous
    June 09, 2009
    PingBack from http://quickdietsite.info/story.php?id=2638