Using the code from the previous post, if I go ahead and drag a new Activity to the design surface and then try and do something simple like renaming it from its automatically generated name (there's a service doing that somewhere I'm sure) then I get an error saying "You need to provide an ITypeProvider" so that looks like a sensible thing to try and improve.

I got bogged down a lot about ITypeProvider because the original sample uses an instance of the TypeProvider class that's already there in the framework but I was reading this post from Jon Flanders which seemed to suggest that you had to write a custom ITypeProvider to get things to work but that hasn't seemed to be the case for me (so far - I'm sure it'll come back to bite me).

ITypeProvider is just a service that the various pieces of componentry that we're plugging together here can use to resolve Types that they don't know about. So, I created an instance of ITypeProvider and added it to my IDesignerHost as a service;

    private void InitialiseTypeProvider()
    {
      TypeProvider t = new TypeProvider(designerHost);
      designerHost.AddService(typeof(ITypeProvider), t);
    }

Now, I want this TypeProvider to be able to "find" all the types that are present on my Toolbox otherwise things aren't going to work very well. So, when I build my toolbox I make sure that the TypeProvider is aware of what I'm up to so as we come across an Assembly that's used to populate the Toolbox I also do;

    private void AddAssemblyToTypeProvider(Assembly a)
    {
      TypeProvider t = (TypeProvider)
        serviceProvider.GetService(typeof(ITypeProvider));

      t.AddAssemblyReference(a.Location);
    }

Note that AddAssemblyReference is a capability of TypeProvider rather than ITypeProvider so I'm cheating a little here by "knowing" the actual type of my ITypeProvider implementation. Also, I actually do this from my Toolbox ListView derived class which feels a bit messy but it works for me right now.

Once I'd plugged in this TypeProvider I found (again, I had to resort to Reflector to work this out) that I wasn't setting the RootComponentClassName for my IDesignerHost and that seemed to be causing me trouble all over the place. I kept getting exceptions saying

" Cannot resolve Type '' "

and I kept pondering where this type with no name was coming from but it turned out to be my fault for not setting this RootComponentClassName so I modified my loading code to try and set that to something sensible;

      string rootComponentName = rootActivity.GetType().FullName;

      Type t = (Type)rootActivity.GetValue(
        WorkflowMarkupSerializer.XClassProperty);

      if (t != null)
      {
        rootComponentName = t.FullName;
      }      

      SetBaseComponentClassName(rootComponentName);

and that seems to resolve it for now.

So, we have a TypeProvider that seems to be working for the moment and I can now rename Activities within the property grid and they do the right thing on the designer. Bingo!

Next, I tried to get the little piece of UI that you get for declarative binding of properties on Activities. The original sample calls this the "ActivityBind" dialog and it tells you how to do it. This is the UI I'm talking about;

 

 

and it's those little blue (they also come in red :-)) circles that I'm trying to get. This one seems fairly simple in that we just have to go ahead and add an implementation of IPropertyValueUIService - the way I read this service is that it's a mechanism via which other parties can add in delegates which get invoked from the property UI in order to add any additional UI that they've got (such as the circles). They can also register callbacks for their UI pieces. The original sample has an implementation here but (to try and understand it) I wrote my own (probably has bugs that the original didn't);

  class MyPropertyValueUIService : IPropertyValueUIService
  {
    public MyPropertyValueUIService()
    {      
    }
    public void AddPropertyValueUIHandler(
      PropertyValueUIHandler newHandler)
    {
      if (valueHandler == null)
      {
        valueHandler = new PropertyValueUIHandler(newHandler);
      }
      else
      {
        valueHandler += newHandler;
      }
    }
    public PropertyValueUIItem[] GetPropertyUIValueItems(
      ITypeDescriptorContext context, PropertyDescriptor propDesc)
    {      
      ArrayList arrayList = new ArrayList();

      valueHandler(context, propDesc, arrayList);

      PropertyValueUIItem[] propertyValueItems =
        arrayList.ToArray(typeof(PropertyValueUIItem)) as
        PropertyValueUIItem[];

      return (propertyValueItems);
    }
    public void NotifyPropertyValueUIItemsChanged()
    {
      if (PropertyUIValueItemsChanged != null)
      {
        PropertyUIValueItemsChanged(this, EventArgs.Empty);
      }
    }
    public void RemovePropertyValueUIHandler(PropertyValueUIHandler newHandler)
    {
      if (valueHandler != null)
      {
        valueHandler -= newHandler;
      }
    }
    public event EventHandler PropertyUIValueItemsChanged;
    private PropertyValueUIHandler valueHandler;
  }

with that in place I get the little UI pieces displaying correctly. The other thing that I picked up from the original sample and from Jon's post was that ISite comes into play for the property grid.

Whilst most of the bits that we've seen so far use IServiceProvider in order to find services, the property grid doesn't.

Instead, it seems that the property grid uses its Site property to find an ISite and ISite has a method on it called GetService which you could easily delegate down to an IServiceProvider implementation.

So...my property grid was still causing me trouble because it wasn't sited (situated?) correctly. The original article says "make sure that the ISite for your property grid is the same as the ISite for your IDesignerHost.RootComponent and so I had to move some code around to make sure that I create my property grid at the same time as I load up the workflow definition and that I set the Site property at that point. Jon's post had an implementation of ISite in it but I haven't found the need to plug in a custom implementation yet.

    private void CreatePropertyGridAndSite()
    {
      propertyGrid = new PropertyGrid();

      propertyGrid.Dock = DockStyle.Fill;

      propertyGrid.Site = 
        designerHost.RootComponent.Site;

      splitContainer2.Panel2.Controls.Add(
        propertyGrid);
    }

So, I can now at least bring up the dialogs for declaratively binding Activity properties and I can also bring up the Condition dialog and the Rules dialog and they all come up fine (they probably don't work too well right now in some respects) and I'm seeing a lot fewer exceptions about ITypeProvider so I'm hoping I've moved forwards a bit but there's still some way to go.

In terms of the project file for where I've got to so far - here it is.