Click here to Skip to main content
12,945,401 members (80,830 online)
Click here to Skip to main content
Add your own
alternative version


74 bookmarked
Posted 19 Feb 2010

The DesignSurface (Extended) Class is Back, Together with a DesignSurfaceManager (Extended) Class and a Form Designer Demo!

, 24 Feb 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Use all the design facilities of the DesignSurfaceExt class together with a Toolbox and PropertyGrid classes.



This article describes DesignSurface/DesignSurfaceManager inherited classes which add to the .NET classes some design facilities (TabOrder, UndoEngine, SnapLines/Grid alignment, ContextMenu with Cut/Copy/Paste commands, Toolbox, and Propertygrid). These classes are hosted inside DLL assemblies and are ready to use inside any .NET solution.


Some people asked me how they could use the DesignSurfaceExt class together with a DesignSurfaceManager class, and for sample code demonstrating how to implement drag and drop operations on the DesignSurface; therefore, I resolved to write a second article explaining these issues. My previous article is available here: DesignSurfaceExt, and introduces you to the DesignSurfaceExt class which extends the .NET DesignSurface class. I extended this class further, improving its design facilities (TabOrder, UndoEngineSnapLines/Grid alignment) with a drag and drop facility and adorning the DesignSurface with a Toolbox and a Propertygrid-like User Control. The code is developed like Chinese boxes: each project encapsulates another one, and each one has a demo form which uses the classes to implement what can be perceived as a Form Designer. Finally, I wrote another User Control to host all these design facilities (exposed via an Interface). Feel free to use the code and to modify it as you like for building your own Form Designer.


It is necessary to be familiar with C# programming. It'd useful to know the concepts used by the .NET designer and to read my previous CodeProject article: DesignSurfaceExt.

How to Use DesignSurfaceExt and DesignSurfaceManagerExt

Inside the attached code, I have included lots of demo projects to show how to use the classes, so I shall spend no more time talking about the usage.

The Nuts and Bolts of the Classes

The classes are structured as Chinese boxes: each class adds design functionalities over another one. From the ground up:

DesignSurfaceExt extends the .NET DesignSurface, adding the following facilities: TabOrder, UndoEngine, Cut/Copy/Paste/Delete commands.

//- DesignSurfaceExt
//-     |
//-     +--|DesignSurface|
//-     |
//-     +--|TabOrder|
//-     |
//-     +--|UndoEngine|
//-     |
//-     +--|Cut/Copy/Paste/Delete commands|

Please refer to the project DemoConsoleForDesignSurfaceExt to see a "Designer", based on DesignSurfaceExt, in action.

DesignSurfaceExt2 extends the previous DesignSurfaceExt, adding Toolbox mechanisms and ContextMenu with Cut/Copy/Paste/Delete commands.

//- DesignSurfaceExt2
//-     |
//-     +--|Toolbox|
//-     |
//-     +--|ContextMenu|
//-     |
//-     +--|DesignSurfaceExt|
//-             |
//-             +--|DesignSurface|
//-             |
//-             +--|TabOrder|
//-             |
//-             +--|UndoEngine|
//-             |
//-             +--|Cut/Copy/Paste/Delete commands|

Please refer to the project "DemoConsoleForDesignSurfaceExt2" to see a "Designer", based on DesignSurfaceExt2, in action.

DesignSurfaceManagerExt manages a collection of DesignSurfaceExt2 instances; it adds a PropertyGrid to each DesignSurfaceExt2 instance:

//- DesignSurfaceExt2
//-     |
//-     +--|PropertyGridHost|
//-     |
//-     +--|Toolbox|
//-     |
//-     +--|ContextMenu|
//-     |
//-     +--|DesignSurfaceExt|
//-             |
//-             +--|DesignSurface|
//-             |
//-             +--|TabOrder|
//-             |
//-             +--|UndoEngine|
//-             |
//-             +--|Cut/Copy/Paste/Delete commands|

Please refer to the project "DemoConsoleForDesignSurfaceManagerExt" to see a "Designer", based on DesignSurfaceManagerExt, in action.

Finally the pDesigner- p(ico) Designer User Control handles all the major aspects of what is perceived as a "Designer" and encompasses the code to manage the above classes.

Please refer to the project "DemoConsoleForpDesigner" to see a "Form Designer", based on pDesigner, in action.

Points of Interest

Every class useful for designing has an accompanying interface. You can call the design facilities of the class through this interface, but if you prefer, you can ignore them and straightaway use the classes.

About DesignSurfaceExt, please see my previous article: DesignSurfaceExt.

About DesignSurfaceExt2: very often, what the user wants for a designing environment is a toolbox. This is usually a nice little list of controls which tell you what kind of controls you can either "point and click" or "drag and drop" on to your surface. The .NET design environment is expressly built to manage these aspects via the ItoolboxService interface. When you implement this interface, you can code most toolbox functionality. But, the key point is the implementation of IToolboxService.DeserializeToolboxItem() together with IToolboxService.SerializeToolboxItem() and IToolboxService.SetSelectedToolboxItem(), together with IToolboxService.GetToolboxItems(). These are the methods called whenever you deploy a control on your brand new design surface. I implemented what is strictly necessary in order to have these functionalities inside DesignSurfaceExt2 (if you launch the demo for this class, you will see that the controls can be sited with both "point and click" and "drag and drop" mechanisms, while if you comment IDesignSurfaceExt2.EnableDragandDrop(), you will lose the "drag and drop" mechanism).

Now, it's time to talk about DesignSurfaceManagerExt. This class is used to extend the .NET 2.0 class DesignSurfaceManager. MSDN states: "Using DesignSurfaceManager is optional, but it is recommended if you intend to have several designer windows." What is this class used for? Basically, it's a central point to manage a collection of DesignSurface objects. Since it is a container of DesignSurface objects, we can use it to contain every object which is a DesignSurface, that is to say, every object which is derived from DesignSurface and therefore also DesignSurfaceManagerExt instances. To do that, we override the DesignSurface CreateDesignSurfaceCore( IServiceProvider parentProvider) method. You can see that the overridden method simply returns a new instance of the DesignSurfaceExt2 class. Inside this method, you can do whatever you want. Anyway, the core concept of DesignSurfaceManagerExt is that "it provides common services that handle event routing between designers [MSDN]". So, pay attention to the private method named Init() inside DesignSurfaceManagerExt: inside the method, I add to the services collection of the DesignSurfaceManagerExt class, my PropertyGrid user-control (actually the PropertyGrid and its ComboBox), virtually letting it be available to each DesignSurface which is created via DesignSurfaceManagerExt. How? See the DesignSurfaceExt2 CreateDesignSurfaceExt2() public method where, after creating the DesignSurface, I put the code necessary to maintain in sync the PropertyGrid with whatever is selected in the current surface.

Another point of interest is the following. MSDN states: "The ActiveDesignSurface property should be set by the designer's user interface whenever a designer becomes the active window". What I understand by this phrase is that it's supposed that I have to implement by myself an Observer Pattern of UI event "the current surface is changed", because only my UI knows when the current surface is changed! Again, inside the Init() method, you can see how the ActiveDesignSurfaceChanged event is managed with a delegate which updates the PropertyGrid (and the ComboBox) by hand.

Finally, some more words about the pDesigner User Control (it stands for picoDesigner) and its interface IpDesigner. I coded them because the final user, when thinking about a Form Designer, expects to find something like this:

//-     +-------------+-----------------------------+-----------+
//-     |toolboxItem1 | ____ ____ ____              |           |
//-     |toolboxItem2 ||____|____|____|___________  +-----------+
//-     |toolboxItem3 ||                          | |     |     |
//-     |             ||                          | |     |     |
//-     |  TOOLBOX    ||      DESIGNSURFACES      | | PROPERTY  |
//-     |             ||                          | |   GRID    |
//-     |             ||__________________________| |     |     |
//-     +-------------+-----------------------------+-----------+

That is to say: a toolbox, a collection of DesignSurfaces which can be switched/added/deleted, and a PropertyGrid which tells her/him the properties of the control currently selected. Good, so here is the interface:

public interface IpDesigner {
    ListBox Toolbox { get; set; }                       //- TOOLBOX
    TabControl TabControlHostingDesignSurfaces { get; } //- DESIGNSURFACES HOST
    PropertyGridHost PropertyGridHost { get; }          //- PROPERTYGRID
    //- DesignSurfaces management section ---------------------------
    DesignSurfaceExt2 ActiveDesignSurface { get; }
    DesignSurfaceExt2 AddDesignSurface<TT>(int startingFormWidth, 
       int startingFormHeight, AlignmentModeEnum alignmentMode, 
       Size gridSize ) where TT : Control;
    void RemoveDesignSurface ( DesignSurfaceExt2 activeSurface );
    //- Editing section  --------------------------------------------
    void UndoOnDesignSurface();
    void RedoOnDesignSurface();
    void CutOnDesignSurface();
    void CopyOnDesignSurface();
    void PasteOnDesignSurface();
    void DeleteOnDesignSurface();
    void SwitchTabOrder();

The User Control pDesigner encompasses all the functionalities said above and the management of the collection of DesignSurfaces via a TabControl used as a concrete container for the surfaces. Here you can see how the TabControl SelectedIndexChanged event is used to propagate the syncing of the PropertyGrid.

The last point which is worthy to be mentioned concerns the service IComponentChangeService. This service is marked as "Non replaceable service", and you can use it to monitor the changes which happen inside the surface; i mean, when a control is added/deleted or simply changed. Adding a handler to the events fired by this service lets you set a fine grained behaviour of your designer according to what happens inside the DesignSurface.


As usual, feel free to use the code and to modify it as you like (and let me know your impressions)!

P.S.: Some of you complained that I posted a bunch of code but there is no accompanying article (by the way, Marc: your comment "very useful" is really a big reward for me). I agree with you, therefore with this update, I dug a little more into the source code to explain some issues ;)


  • 19 February 2010 - First submission of the article/code.
  • 22 February 2010 - Updated the "Points of Interest" section of the article.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Paolo Foti
Software Developer (Senior)
Italy Italy
I started coding in 1984 on a ZX Spectrum. From the Sinclair Basic I jumped straight to C++ (which I use since 1992). I wrote code in assembly 386, ANSI C++ (I love it) and VisualBasic 6.0 (urgh!!!); nowadays I write code in C# 4.0!

I was born in 1968 in Italy and I live in the north west of my country (near Venice). I work as a Project Leader/Senior Developer.

Computer Science interests: I like coding 3D-GameEngine and OpenGL applications.

Sport and hobbies: Martial Arts, Latino Dance, travels, reading and writing novels.

You may also be interested in...

Comments and Discussions

QuestionHow to disable the form guides to avoid resizing (only in the Form) Pin
xlsprogrammer5-May-17 23:34
memberxlsprogrammer5-May-17 23:34 
QuestionIf you want to select all the controls or make the controls aligned Pin
jiangma8-Mar-17 15:03
memberjiangma8-Mar-17 15:03 
BugImplement the designer with System.ComponentModel.Design.DesignSurface, when you open a designer, turn off a designer, and the rest of the designer's controls can not change the control's size by dragging the mouse Pin
jiangma7-Mar-17 14:22
memberjiangma7-Mar-17 14:22 
GeneralRe: Implement the designer with System.ComponentModel.Design.DesignSurface, when you open a designer, turn off a designer, and the rest of the designer's controls can not change the control's size by dragging the mouse Pin
jiangma7-Mar-17 14:27
memberjiangma7-Mar-17 14:27 
GeneralVersione WPF del designer Pin
flik888812-Apr-16 21:11
memberflik888812-Apr-16 21:11 
BugMemory linger. Pin
Iker874-Jun-15 10:54
memberIker874-Jun-15 10:54 
QuestionLoading form from file Pin
matt mann8-Feb-15 12:37
membermatt mann8-Feb-15 12:37 
QuestionHow can I enable/disable grid option & zoom in/out & ViewSize in the menu Pin
Hyun-woo Jang4-Nov-14 17:07
memberHyun-woo Jang4-Nov-14 17:07 
QuestionHow I can use the LineShape Control from the VB PowerPack? Pin
Member 1103435725-Aug-14 1:21
memberMember 1103435725-Aug-14 1:21 
QuestionHow to incorporate the snaplines into my form? Pin
colero14-Aug-14 3:14
membercolero14-Aug-14 3:14 
QuestionAwwsome. Pin
vighnu22-Oct-13 3:05
membervighnu22-Oct-13 3:05 
Questionroot form Pin
filmee246-Aug-13 2:14
memberfilmee246-Aug-13 2:14 
QuestionDisable "point and click" action on design surface. Pin
redhatee200613-Jul-12 2:29
memberredhatee200613-Jul-12 2:29 
QuestionManually adding controls Pin
redhatee200630-May-12 2:39
memberredhatee200630-May-12 2:39 
QuestionKudos - Using for XML Form System Pin
SRoyalty9-Feb-12 23:13
memberSRoyalty9-Feb-12 23:13 
QuestionRe: Kudos - Using for XML Form System Pin
jmptrader23-Apr-12 11:03
memberjmptrader23-Apr-12 11:03 
Questioni want Events on controls Pin
srinivas vaddepally15-Nov-11 18:08
membersrinivas vaddepally15-Nov-11 18:08 
GeneralZoom feature? Pin
Taita18-May-11 7:25
memberTaita18-May-11 7:25 
GeneralMy vote of 5 Pin
gorallo5-May-11 6:29
membergorallo5-May-11 6:29 
QuestionAre the controls printable? Pin
nessy0028-Mar-11 4:51
membernessy0028-Mar-11 4:51 
GeneralMultiple Selection Pin
tomcharnley10-Mar-11 21:23
membertomcharnley10-Mar-11 21:23 
QuestionHow to save or load the form code? Pin
xinset12-Aug-10 15:08
memberxinset12-Aug-10 15:08 
GeneralGreat Work - A Question on Control events Pin
David Ballantyne17-May-10 6:07
memberDavid Ballantyne17-May-10 6:07 
GeneralRe: Great Work - A Question on Control events Pin
Member 375256129-Jan-13 0:02
memberMember 375256129-Jan-13 0:02 
QuestionHow do I check If is control is dropped/created within a Parent control or in RootComponent ? Pin
Ruchit S.9-Apr-10 3:35
memberRuchit S.9-Apr-10 3:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170518.1 | Last Updated 24 Feb 2010
Article Copyright 2010 by Paolo Foti
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid