The Design Container
No matter what you're designing, be it Windows Forms or Web Forms, everything in design mode is said to be on the Design Surface . What this means is that it's in the design container. Forms and controls are hierarchical in nature, but everything is also in the design container, which is a one-level collection. This container has the code to discover and instantiate designers for objects, and also dispose of them when they're done.
As you probably already know, all designers implement the IDesigner
interface. However, there is always one special designer in a document which has to implement IRootDesigner
. This is the one that acts as a parent to all the rest, and is responsible for providing the interface you use to view the object you're designing. This is always the first object to be added to the design container. The framework provides three root designers - for Forms, UserControls and Components. You've probably seen all these if you've used the various designable types in Visual Studio. The framework doesn't contain any Web Forms root designers.
The root designer is a great idea, it means you don't have to write any special hosting code no matter what you're designing. Once your hosting framework is in place you can design anything that offers one.
The Designer Host
This is where you start when hosting designers (obviously). It all begins with the IDesignerHost
interface, which you might well have already used from designers you've written. It exposes the design container, the root component, and methods for creating components and getting their designers. It also provides the support for designer transactions and acts as a service container.
Although we'll be implementing quite a few interfaces apart from this one, the most important two are ISelectionService
and IComponentChangeService
, because every designer uses them. Thankfully most of the .NET controls behave gracefully when they fail to find a service implemented, if they didn't we would have a much harder time getting started.
The core designer hosting architecture is split in to several interfaces, but since they are tightly bound together we will be implementing the most important ones all in one class:
-
IDesignerHost
- The core interface. -
IContainer
- The container that holds all components on the design surface. -
IComponentChangeService
- Used to broadcast events when components change. -
IExtenderProvider
- Used to give components a configurable name.
Design Sites
In order to be on the design surface, a class has to implement IComponent
. This means it has a Site property, which is how its name is kept track of at design time. For every object that is placed on the design surface an object implementing ISite needs to be assigned to it. It's through this that the components are able to request services, establish that they are in design mode and get their name.
We will create a class, DesignSite, that implements ISite
and provides this necessary information. Anyway, enough with the theory, let's get down to business.
Comments