If you’re just jumping in, you may want to start from the beginning: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx
Beginning the Designer
In case you’re not pouring over the source code with interest and reverence, let’s take a quick snapshot of the structure that is emerging:


There’s very little in the IoC or HTLayout projects so far, but it seems very clean up to this point. I have also done nearly nothing related to my core problem of a Design Time environment for Silverlight: the Design project stands empty. It seems sensible enough to work from left to right for the time being, so let’s begin with the Toolbox.
Designable
The next step is to create an abstraction for what we are going to be working with. In the VS2008 design time environment the coin of the realm is the System.ComponentModel.Component. In many ways I didn’t like this since one is nearly always casting Component to Control. Creating an interface that gives us a grammar for something which is “designable” and also has a visual representation will be a better place to start.
namespace DamonPayne.AGT.Design
{
public interface IDesignableControl
{
/// <summary>
/// Visual representation of this IDesignableControl
/// </summary>
Type VisualType { get; }
/// <summary>
///
/// </summary>
bool Scalable { get; }
/// <summary>
/// Should the designer allow transformations such as rotation to be applied?
/// </summary>
bool Transformable { get; }
string Name { get; set; }
}
}
That’s all I’ve got for now. Clearly I’ve thought this through…
Toolbox Service
A toolbox is a thing that displays a list of things you can drag out into another thing. It is a thing as well as a meta-thing. Beginning in Visual Studio 2005 we had the notion of a categorized toolbox. I like that, so the next step is to decide on the starting point for a Toolbox service. Keeping with the Microsoft design for now, I create a ToolboxItem.
namespace DamonPayne.AGT.Design.Types
{
public class ToolboxItem
{
public ToolboxItem():this("Unknown", "No description",null)
{
}
public ToolboxItem(string name, string desc, Type type)
{
Name = name;
Description = desc;
Type = type;
}
public string Name { get; set; }
public string Description { get; set; }
public Type Type { get; set; }
}
}
The IToolboxService is straightforward.
namespace DamonPayne.AGT.Design.Contracts
{
public interface IToolboxService : IService
{
void AddItem(ToolboxItem item);
void AddItem(ToolboxItem item, string category);
ToolboxItem SelectedItem { get; }
void RemoveItem(ToolboxItem item);
}
}
That will serve for now. Before I get into creating some funky purple couches and speakers in Expression Blend, I need to make sure my framework supports my next intended action.
public partial class ToolboxView : UserControl, IView, IToolboxService
It makes a lot of sense for the visual toolbox UserControl to implement the IToolboxService interface. Who better? Now I need to take a look at my framework already. Things that I need to create as top level objects go through the ControlBuilder. Things that need to provide service implementations to other components are created when their Type is registered with the ServiceManager. I’m trying to have it both ways and I can’t without doing more work. Since I envision the same situation for the designer surface and property grid later on this deserves some thought.
1. I could create a non-visual toolbox class that knows about the ToolboxView and have this class implement the IToolboxService instead. The ToolboxView would have to provide public methods for all the appropriate operations.
2. In addition to #1, I could change ToolboxView to have a “Visual” property that could be set at a later time.
3. I could change ServiceManager such that the ToolboxView (while implementing IToolboxService) is actually instantiated up front just like other service providers and somehow requested.
4. I could strengthen the loving relationship between ComponentBuilder and ServiceManager.
Recall the public interface to ComponentBuilder:
public static T Create<T>() where T :new ()
I could fairly easily detect here that I’ve been asked to create something which is potentially both a service provider and service consumer and pass it off to ServiceManager after fully building it. Unless I receive one metric ton of hatemail, I will take this approach for now. ComponentBuilder can call this entirely new ServiceManager.ManageInstance method:
public static void ManageInstance(object provider)
{
Type baseServiceType = typeof(IService);
Type t = provider.GetType();
Type[] interfaces = t.GetInterfaces();
foreach (Type iface in interfaces)
{
if (iface.InterfaceExtends(baseServiceType))
{
_services.Add(iface, provider);
}
}
}
The main issue that I can foresee is getting into trouble with multiple instances of an IService being provided by different Types. If this situation arises, some form of discriminator will need to be introduced. For now, though, this is a good stopping point. In the next article we can begin the visual implementation of the ToolboxView.
Source code: DamonPayne.AGT[3].zip (672.51 KB)