The official Fatica Labs Blog! RSS 2.0
# Sunday, March 06, 2011

When we host the activities palette, we notice a blue gear without meaning on each of our activity. This should be easy to solve, but it is not so easy for the built in activities. So what we have till now is:

image

We want to have something better, even for the standard activities. In WF4 is not said that the ToolboxBitmapAttribute, the one used to bind the image to show in the palette is attached to all activities, and we can say it is not for sure for the built in activities. Fortunately the WF4 architecture provides a way to attach attributes to objects runtime, this is achieved via the AttributeTableBuilder class, that provide a way to register and apply attributes runtime to objects via another helper class: MetadataStore. So if we have somewhere these icons, we can attach the proper attribute runtime, and all is done, but where to find it ?  Do we have proper licensing to distribute it ? A reply to this question could be found here, and in particular in the Brannon King’s comment. Brannon show how to grab the icons from the redistributable System.Activities.Presentation dll, and more, it post the whole code to provide the attributes creation and binding, and graphics retrieval too. So we grab this great work and we add it in our helper class ToolboxItemSource, so we can ensure designer has the proper graphic information for both built in and custom activities we add as a source. Let’s have a look at the code, that is just a little modified:

   1:                  var builder = new AttributeTableBuilder();
   2:                  foreach (var item in query)
   3:                  {
   4:                      AddIconAttributes(item, builder);
   5:                  }
   6:                  MetadataStore.AddAttributeTable(builder.CreateTable());

Well this portion is in the member function AddTools, already present in our helper, we basically creates an AttributeTableBuilder, then we add the resources attributes, and then we realize, at line 6, the association. Let’s have a look at the Brannon’s code, that we embed in the AddIconAttributes:

   1:        protected static  bool AddIconAttributes(Type type, AttributeTableBuilder builder)
   2:          {
   3:              var secondary = false;
   4:              var tbaType = typeof(ToolboxBitmapAttribute);
   5:              var imageType = typeof(System.Drawing.Image);
   6:              var constructor = tbaType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { imageType, imageType }, null);
   7:              string resourceKey = type.IsGenericType ? type.GetGenericTypeDefinition().Name : type.Name;
   8:              int index = resourceKey.IndexOf('`');
   9:              if (index > 0)
  10:              {
  11:                  resourceKey = resourceKey.Remove(index);
  12:              }
  13:              if (resourceKey == "Flowchart")
  14:              {
  15:                  resourceKey = "FlowChart"; // it appears that themes/icons.xaml has a typo here
  16:              }
  17:              resourceKey += "Icon";
  18:              Bitmap small, large;
  19:              object resource = resources[resourceKey];
  20:              if (!(resource is DrawingBrush))
  21:              {
  22:                  resource = resources["GenericLeafActivityIcon"];
  23:                  secondary = true;
  24:              }
  25:              var dv = new DrawingVisual();
  26:              using (var context = dv.RenderOpen())
  27:              {
  28:                  context.DrawRectangle(((DrawingBrush)resource), null, new Rect(0, 0, 32, 32));
  29:                  context.DrawRectangle(((DrawingBrush)resource), null, new Rect(32, 32, 16, 16));
  30:              }
  31:              var rtb = new RenderTargetBitmap(32, 32, 96, 96, PixelFormats.Pbgra32);
  32:              rtb.Render(dv);
  33:              using (var outStream = new MemoryStream())
  34:              {
  35:                  BitmapEncoder enc = new PngBitmapEncoder();
  36:                  enc.Frames.Add(BitmapFrame.Create(rtb));
  37:                  enc.Save(outStream);
  38:                  outStream.Position = 0;
  39:                  large = new Bitmap(outStream);
  40:              }
  41:              rtb = new RenderTargetBitmap(16, 16, 96, 96, PixelFormats.Pbgra32);
  42:              dv.Offset = new Vector(-32, -32);
  43:              rtb.Render(dv);
  44:              using (var outStream = new MemoryStream())
  45:              {
  46:                  BitmapEncoder enc = new PngBitmapEncoder();
  47:                  enc.Frames.Add(BitmapFrame.Create(rtb));
  48:                  enc.Save(outStream);
  49:                  outStream.Position = 0;
  50:                  small = new Bitmap(outStream);
  51:              }
  52:   
  53:              var tba = constructor.Invoke(new object[] { small, large }) as ToolboxBitmapAttribute;
  54:              builder.AddCustomAttributes(type, tba);
  55:              return secondary;
  56:          }

 

I’ve just stored the resources needed in a local static dictionary, by this call:

 

   1:  static ResourceDictionary resources = new ResourceDictionary
   2:   { Source = new Uri("pack://application:,,,/System.Activities.Presentation;component/themes/icons.xaml") };

 

Basically Brannon’s code use the assumption the icon is the name of the activity suffixed by “Icon”, except for a typo on FlowChart solved at lines 13-16. Then he create a bitmap and it save it on a memory stream. That stream is then use as an argument for ToolboxBitmapAttribute. So we put all together and we obtain this new presentation:

image

So we got rid of the blue gear. We will need the property editor next, always a XAML only strategy to present it has to be provided, probably with the same strategy we used for the main editor itself.

Have a look at the code here.

Sunday, March 06, 2011 10:10:10 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
Programmin | Recipes | ReHosting | WF4

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 123
This blog visits
All Content © 2014, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano