Library tutorials & articles

Hosting Windows Forms Designers

Making it Work

That's about it for the DesignerHost and its related classes. The way we've written it, all it needs to be instantiated is a ServiceContainer instance. The framework provides a simple implementation of this, so we'll just use that. We want a very simple design surface so we'll just make a form with one side reserved for a propertygrid.

Now, how do we actually put our DesignerHost to use? It comes back to the Root Designer we discussed earlier. The key method is has is GetView, which returns a Control that can be added to any other form or control. This control is what you see when you look at a form in design view; it has a white background, and shows the form in design mode sitting in the top left.

Once we have created our DesignerHost, we (the host application) needs to subscribe to the SelectionChanged event of the ISelectionService interface that we already implemented. This is so that we can display the properties of the selected objects in our propertygrid.

We will use the following code to instantiate a form, put it in to design mode by adding it to our host, get its design view and add that view to the form:

private void Initialize()
{
    IDesignerHost host;
    Form form;
    IRootDesigner rootDesigner;
    Control view;
    // Initialise service container and designer host
    serviceContainer = new ServiceContainer();
    serviceContainer.AddService(typeof(INameCreationService),
    new NameCreationService());
    serviceContainer.AddService(typeof(IUIService), new UIService(this));
    host = new DesignerHost(serviceContainer);
    // Add toolbox service
    serviceContainer.AddService(typeof(IToolboxService), lstToolbox);
    lstToolbox.designPanel = pnlViewHost;
    PopulateToolbox(lstToolbox);
    // Add menu command service
    menuService = new MenuCommandService();
    serviceContainer.AddService(typeof(IMenuCommandService), menuService);
    // Start the designer host off with a Form to design
    form = (Form)host.CreateComponent(typeof(Form));
    form.TopLevel = false;
    form.Text = "Form1";
    // Get the root designer for the form and add its design view to this form
    rootDesigner = (IRootDesigner)host.GetDesigner(form);
    view = (Control)rootDesigner.GetView(ViewTechnology.WindowsForms);
    view.Dock = DockStyle.Fill;
    pnlViewHost.Controls.Add(view);
    // Subscribe to the selectionchanged event and activate the designer
    ISelectionService s = (ISelectionService)serviceContainer.GetService(
    typeof(ISelectionService));
    s.SelectionChanged += new EventHandler(OnSelectionChanged);
    host.Activate();
}

Conclusion

Reading over the code should fill in any gaps that I missed out while writing this. Hopefully this article will encourage more people to make use of the designer architecture in their own applications.

I have provided an example project that covers everything in this article (just click the download link above). Thanks to Ken Swinney for the VB version.

Comments

  1. 15 Jun 2009 at 14:22

    How would I go about saving a form that I have designed?

  2. 10 Dec 2008 at 11:35
    I know I'm replying to very old comments but, for the sake of keeping all info in ONE place and not distributed through different message boards, heres my 2 cents. For persistence, look for designer serialization visibility attribute and the related interfaces (IDesignerSerializationService and such). It's my though that when a component is loaded, the designer must know which properties need persistence. Either that or it uses discovery to find these when ever the designer code file is viewed. For the guy doing the XAML forms thing, changing the name of a component should raise ComponentRenaming/ComponentRenamed on IComponentChangeService or, at the very least, check INameCreationService to find if the name is valid.
  3. 20 Jul 2007 at 20:49

    I have (am still) modifying this code to create a stand-alone Xaml generator for forms. The Xaml is structured for direct consumption by Windows Presentation Foundation. This was a great starting place.

    In the course of my modifications and testing, I found a couple of bugs in the code which you may wish to correct in your source.

    The Name property is listed twice in the property grid.

    If you add a control (i.e. a Button), then change the name from the default (Button1) to anything else, then add another button, you get an unhandled exception. This does not occur if all like controls are added first then the names are modified. The cause is when the control is first added to the designer, it is added to the DesignerHost components collection using the default (Button1) control name as a key. When the Name property is updated, the components collection is not. When adding a second like control, the DesignerHost attempts to add it using the default name as well. However, since the first control was renamed, the default name of the second control is the same as it was for the first (Button1). An unhandled exception is thrown when the second control is added because the components collection already contains a control with the same key value.

    I corrected this by attaching a handler to the PropertyValueChanged event of the PropertyGrid which removes the original entry for the control and readds it with the new name as the key whenever the Name property value is changed.

  4. 17 Jan 2007 at 08:51
    hallo,
    how to change Designer for design PocketPC components?

    htx

    v!tek
  5. 30 Oct 2006 at 09:45

    Hi Tim, great article. I am currently creating a designer in a similar manner to your article, used to create pdf files. I am using it to add only textboxes and pictures, and can save the data to a database.  However I need to bring back the objects and add them to the form programmatically so the user can edit the objects (change the positions etc) Do you know how (or explain how) to add items to the designer surface programmatcally without using the drag and drop from the toolbox

    Thanks

    John Harry

  6. 19 Sep 2006 at 21:39

    Tim:

    Thanks for your nice article.

    How can I get the location of a control in the design surface. I want to show the coordinates when the user moves the control, but I can't figure how!





  7. 11 Jul 2006 at 08:37
    Did you ever figure out how to remove controls from the form?  I need to do that same now

  8. 20 Nov 2005 at 17:52

    Did you figure it out how to persist the designer content? I would appreciate any help on this
    Thanks
    Sgirase

  9. 13 Oct 2005 at 13:00

    Hi!


    That article is really great.  It gave me useful hints to start my application in perfectmanner , which looks like an .Net IDE . but can you please tell me how to remove a control from the designer form ....




  10. 15 Aug 2005 at 20:17

    Hello Tim,


     Thank you very much for this excellent article.  


     We have developed a graphical macro language in C# for our customers and one of the remaining hurdles that we have is the ability to edit the location of controls on a runtime form.  


     When the customer wants to edit our form, we scan our macro and generate controls on the form based upon the macro content.
     We would then like to display that form with the controls where the customer can position and size those controls like you can in this Designer example.  We would then iterate through the list of controls and remember their locations and sizes within the macro.


     Can you please lead us in the right direction?  We have been searching, trying, and reading many examples to no avail.  It appears that you possess this knowledge and could help us.  We are not inexperienced developers, I personally have been a software developer for 22 years in many languages.


      For example, how would you modify this example so that controls can be placed on the form with out the user clicking on the designer surface?


    Thank you very much for your reply,
    Rick Wirch

  11. 12 Aug 2005 at 01:56

    Good question ... I am actually tasked with building a Web Forms Designer.  I can load ASP.NET controls into my toolbox but of course can't drop those controls onto a Windows forms.  Can somebody help me!!  


    Much appreciated -
    Jon

  12. 15 Mar 2005 at 13:23

    Is it possible to use a treeview for that?

  13. 09 Feb 2005 at 12:45
    Hi!

    That article is really great.
    It gave me the needed hints to step into this subject as deep as I wanted to. As i'm currently trying tom write a lightweight IDE for customumizing my own applications, i need to know, how the content auf the designer could be persisted and reloaded.
    Is there any standard-mechanism for that, or will I have to implement my own handlers?

    Any help would be appreciated!
  14. 15 Dec 2004 at 07:28
    what about a Web Forms designer?
    Its possible to do something similar to your example using web forms designer?
  15. 08 Apr 2004 at 05:29

    This article is simply great. I wish to see more like this one.
    Arthur

  16. 01 Jan 1999 at 00:00

    This thread is for discussions of Hosting Windows Forms Designers.

Leave a comment

Sign in or Join us (it's free).

Tim Dawson
AddThis

Related podcasts

  • A Practical Look at Silverlight 2 Part 1

    Now that Silverlight 2 is at the Olympics and making a big splash, we wanted to explore this fascinating technology more. Microsoft Silverlight 2 is a cross-browser, cross-platform, and cross-device plug-in for delivering the next generation of .NET based media experiences and rich interactive ap...

Events coming up

  • Nov 18

    15 Minutes of Fame

    Dresher, United States

    This is a yearly tradition. We select 10 of the favorite speakers from monthly meetings, code camps, and hands on labs. Each one does a 15 minute talk on their favorite .NET technology. This is our 10th anniversary so we plan a gala event with special prizes and refreshments.

Want to stay in touch with what's going on? Follow us on twitter!