Members

Technology Zones

Articles

Hosted By

MaximumASP

Info

Rated
Read 32,238 times

Contents

Downloads

Related Categories

Hosting Windows Forms Designers - Implementing ISite and more

divil

Implementing ISite and more

Implementing ISite

Our ISite implementation, called DesignSite, is going to be a poweful little beast that also implements IDictionaryService, the interface that for some reason some components use instead of using their own internal dictionaries. There isn't really much point going in to any of the stuff in this class in detail because it's mostly just template code except in the setter for the Name property.

The setter needs to check there isn't already a component with the name passed in the container. If there isn't, it can then proceed. To play friendly with the rest of the design environment, it must cause the IComponentChangeService implementation to raise the OnComponentChanging, OnComponentRename and OnComponentChanged events in that order while the change is made.

Implementing IComponentChangeService

This is an easy one. All this interface has is seven events and two methods which raise two of the events. All we do is add code for those two methods, and add another, internal method which is needed for our DesignSite class to raise the ComponentRename event. Although implementing this interface is easy, what's hard is working out where else in our implemented code to raise the events on it.

public void OnComponentChanged(object component, System.ComponentModel.MemberDescriptor
member, object oldValue, object newValue)
{
    if (ComponentChanged != null)
        ComponentChanged(this, new ComponentChangedEventArgs(component,
        member, oldValue, newValue));
}
public void OnComponentChanging(object component,
System.ComponentModel.MemberDescriptor member)
{
    if (ComponentChanging != null)
        ComponentChanging(this, new ComponentChangingEventArgs(component, member));
}
internal void OnComponentRename(object component, string oldName, string newName)
{
    if (ComponentRename != null)
        ComponentRename(this, new ComponentRenameEventArgs(component,
        oldName, newName));
}
public event System.ComponentModel.Design.ComponentEventHandler ComponentAdded;
public event System.ComponentModel.Design.ComponentEventHandler ComponentAdding;
public event System.ComponentModel.Design.ComponentChangedEventHandler ComponentChanged;
public event System.ComponentModel.Design.ComponentChangingEventHandler ComponentChanging;
public event System.ComponentModel.Design.ComponentEventHandler ComponentRemoved;
public event System.ComponentModel.Design.ComponentEventHandler ComponentRemoving;
public event System.ComponentModel.Design.ComponentRenameEventHandler ComponentRename;

Implementing IDesignerHost

This should really have been the class we started with, but IDesignerHost, IContainer, ISite and IComponentChangeService all depend on each other so much it makes sense to write about them in the order it's necessary to code them in. I'll cover the implementations of the members on IDesignerHost as I write them as best I can.

  • Activate - This method is called to activate the root component. Our implementation will grab ISelectionService and set the root component as the primary selection.
  • CreateComponent - This method is used by designers to have the host environment create an instance of a class that is to be situated on the design surface. Calling it is functionally identical to creating instance themselves then adding it to the container.
  • DestroyComponent - This is called to remove a component from the design surface and dispose of it properly. This method is also responsible for using IComponentChangeService to let others know what is going on as the component is being removed.
  • CreateTransaction - Creates an instance of our template DesignerTransaction class (I'll come on to that in a minute) and adds it to the stack of transactions.
  • GetDesigner - We just use our designers hashtable to return the designer associated with the passed component.
  • GetType - We check if there is an ITypeResolutionService available, and if so use it. If not, return Type.GetType() instead.
  • Container - Just return the instance of the class since it implements IContainer itself.
  • InTransaction - Return true if the number of transactions in our stack is greater than zero.
  • Loading - For this example we are not concerned with loading hosts, so just return false.
  • RootComponent - Return rootComponent, the first component added to our container.
  • RootComponentClassName - Return the name of the class the first component added to our container was created from.
  • TransactionDescription - Return the name of the transaction at the top of our stack, if there is one.

Designer Transactions

Every small change to a component should go through the IComponentChangeService, but when lots of small changes need to be wrapped up logically, that's where designer transactions come in. If we were writing a full-scale implementation of a design environment, we would keep track of these for undo/redo support.

There is no interface to be implemented here, we just need to inherit the abstract class DesignerTransaction with our own. All ours will do is make sure the appropriate events are raised by the host when the transaction is committed or cancelled.

Comments

  • Re: [4351] Hosting Windows Forms Designers

    Posted by timker on 20 Jul 2007

    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 p...

  • Re: Hosting Windows Forms Designers - PocketPC

    Posted by vitek on 17 Jan 2007

    hallo,
    how to change Designer for design PocketPC components?

    htx

    v!tek

  • Re: [4351] Hosting Windows Forms Designers

    Posted by jharry on 30 Oct 2006

    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&n...

  • Control coordinates

    Posted by hugobq on 19 Sep 2006

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

  • Re: Remove controls from te form

    Posted by NewbieDude on 11 Jul 2006

    Did you ever figure out how to remove controls from the form?  I need to do that same now