Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / Windows Forms

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

Rate me:
Please Sign up or sign in to vote.
4.93/5 (36 votes)
24 Feb 2010CPOL6 min read 93.2K   7.6K   84   41
Use all the design facilities of the DesignSurfaceExt class together with a Toolbox and PropertyGrid classes.

Demo_For_pFDesigner.png

Abstract

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.

Introduction

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.

Background

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:

C#
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();
}//end_interface

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.

Conclusion

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 ;)

History

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

License

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


Written By
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.

Comments and Discussions

 
Question.NET Core Pin
AhmadJ198221-Nov-20 13:06
AhmadJ198221-Nov-20 13:06 
Questioncopy between forms Pin
Member 1489925026-Jul-20 4:33
Member 1489925026-Jul-20 4:33 
QuestionGreat work. Pin
marlofs8-Oct-19 21:04
marlofs8-Oct-19 21:04 
QuestionHow to load and save designsurface design to file Pin
Jigar Prajapati (King Sanu)14-Aug-19 21:13
Jigar Prajapati (King Sanu)14-Aug-19 21:13 
QuestionAdd designer to existing controls Pin
hrahihrahi4-Mar-18 21:19
hrahihrahi4-Mar-18 21:19 
QuestionHow to disable the form guides to avoid resizing (only in the Form) Pin
xlsprogrammer5-May-17 23:34
xlsprogrammer5-May-17 23:34 
QuestionIf you want to select all the controls or make the controls aligned Pin
jiangma8-Mar-17 15:03
jiangma8-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
jiangma7-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
jiangma7-Mar-17 14:27 
GeneralVersione WPF del designer Pin
flik888812-Apr-16 21:11
flik888812-Apr-16 21:11 
BugMemory linger. Pin
Iker874-Jun-15 10:54
Iker874-Jun-15 10:54 
QuestionLoading form from file Pin
matt mann8-Feb-15 12:37
matt mann8-Feb-15 12:37 
AnswerRe: Loading form from file Pin
Jigar Prajapati (King Sanu)14-Aug-19 21:12
Jigar Prajapati (King Sanu)14-Aug-19 21:12 
QuestionHow can I enable/disable grid option & zoom in/out & ViewSize in the menu Pin
Hyun-woo Jang4-Nov-14 17:07
Hyun-woo Jang4-Nov-14 17:07 
QuestionHow I can use the LineShape Control from the VB PowerPack? Pin
Cherub133725-Aug-14 1:21
Cherub133725-Aug-14 1:21 
QuestionHow to incorporate the snaplines into my form? Pin
colero14-Aug-14 3:14
colero14-Aug-14 3:14 
Hello, first I would like to congratulate you for your project, it is impressive and you did an amazing job.
I would like to know if it is possible to incorporate only the snaplines technique into my own form.I am building a project where the user will be able to draw squares on the form and the squares will be transformed into buttons, and also the user can resize and reposition the buttons, been said that i would like to have the snaplines when the user moves the buttons and when he resizes it.

Here is an example of what the project already does: https://www.youtube.com/watch?v=DwBTXMA3eXs[^]

Hope to hearing from you soon. Thank you.
QuestionAwwsome. Pin
vighnu22-Oct-13 3:05
vighnu22-Oct-13 3:05 
Questionroot form Pin
filmee246-Aug-13 2:14
filmee246-Aug-13 2:14 
QuestionDisable "point and click" action on design surface. Pin
redhatee200613-Jul-12 2:29
redhatee200613-Jul-12 2:29 
QuestionManually adding controls Pin
redhatee200630-May-12 2:39
redhatee200630-May-12 2:39 
QuestionKudos - Using for XML Form System Pin
SRoyalty9-Feb-12 23:13
SRoyalty9-Feb-12 23:13 
QuestionRe: Kudos - Using for XML Form System Pin
jmptrader23-Apr-12 11:03
professionaljmptrader23-Apr-12 11:03 
Questioni want Events on controls Pin
srinivas vaddepally15-Nov-11 18:08
srinivas vaddepally15-Nov-11 18:08 
GeneralZoom feature? Pin
Maurizio Battiston18-May-11 7:25
Maurizio Battiston18-May-11 7:25 
GeneralMy vote of 5 Pin
Wojciech Nagórski5-May-11 6:29
Wojciech Nagórski5-May-11 6:29 

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.