locked
How can I use the same icon in the toolbox and on the design surface? RRS feed

  • Question

  • This is SUCH A PAIN IN THE ____.

    I definitely want to use the SAME IMAGE from the SAME IMAGE FILE for both the toolbox and the design surface.  Anything else is stupid.

    To use the image in the toolbox via the ToolboxIconAttribute, the image has to be 1) a bmp, 2) have its build action be an "Embedded Resource" (pay attention here or look stupid).  

    However, WPF pack uri's CANNOT be used to find images whose build action is "Embedded Resource", only "Resource" files can be referred to via a pack:// Uri.

    I also cannot add the images to the project as links and then set the build action differently (same physical image file but embedded twice, oh well) as you cannot link to the same file twice within the same project.

    As I see it, I have three choices:

    1) Try to set the designer icon via codebehind (a pain in the ____; not even sure if it will work)

    2) Copypaste the images, perhaps as a pre-build step (omgwtf)

    3) Completely reorganize the structure of the solution so that designers and activities live in different assemblies (really?  reminds me of beta1 days and mixing workflow and wpf in the same assembly)

     

    Is there any satisfactory solution for this?

    Tuesday, September 28, 2010 3:42 PM

Answers

  • Sorry Will, for not reading the question carefully enough,
    I had it in my head you were talking about the ToolboxItemWrappers, and code beside files for the rehosted app.
    It seems like you are talking about ToolboxBitmapAttribute instead.

    I don't think code beside can do anything useful for the attribute, and using EmbeddedResource does seem like the only way to go to keep the ToolboxBitmapAttribute happy.

    So if the question is really 'how do I extract and use the bitmap icon' in my activity designer, if it is done using build action EmbeddedResource?' Doing this from codebehind seems like a perfectly fine approach:

    public CodeActivity1Designer()
      {
       InitializeComponent();
       
       Stream manifestResourceStream = typeof(CodeActivity1Designer)
        .Module.Assembly.GetManifestResourceStream(
        typeof(CodeActivity1Designer), "foo.bmp");
    
       var bmpframe = BitmapFrame.Create(manifestResourceStream);
    
       this.Icon = new DrawingBrush
       {
        Drawing = new ImageDrawing
        {
         Rect = new System.Windows.Rect(0, 0, 16, 16),
         ImageSource = bmpframe
        }
       };
      }
    • Edited by Tim Lovell-Smith Wednesday, September 29, 2010 10:24 PM source code readability
    • Proposed as answer by Tim Lovell-Smith Thursday, September 30, 2010 8:50 PM
    • Marked as answer by Andrew_Zhu Tuesday, October 5, 2010 6:35 AM
    Wednesday, September 29, 2010 10:20 PM

All replies

  • Hi Will,

    I don't know if Option 1 gets you far. Option 3 might be a good idea for runtime efficiency of loading activity classes but that is unrelated to the question.

    The best workaround idea I have right now is to retemplate the toolbox control's toolboxitem part, using an approach near the bottom here:

    http://blogs.msdn.com/b/tilovell/archive/2010/03/08/the-workflow-4-0-custom-activity-icon-and-toolbox-icon-faq.aspx

    then you can fix the toolbox control to look things up in a sane and satisfactory way.

    Tim

    Wednesday, September 29, 2010 6:27 PM
  • Unfortunately, that only works when rehosting and not in Visual Studio.
    Wednesday, September 29, 2010 7:00 PM
  • Sorry Will, for not reading the question carefully enough,
    I had it in my head you were talking about the ToolboxItemWrappers, and code beside files for the rehosted app.
    It seems like you are talking about ToolboxBitmapAttribute instead.

    I don't think code beside can do anything useful for the attribute, and using EmbeddedResource does seem like the only way to go to keep the ToolboxBitmapAttribute happy.

    So if the question is really 'how do I extract and use the bitmap icon' in my activity designer, if it is done using build action EmbeddedResource?' Doing this from codebehind seems like a perfectly fine approach:

    public CodeActivity1Designer()
      {
       InitializeComponent();
       
       Stream manifestResourceStream = typeof(CodeActivity1Designer)
        .Module.Assembly.GetManifestResourceStream(
        typeof(CodeActivity1Designer), "foo.bmp");
    
       var bmpframe = BitmapFrame.Create(manifestResourceStream);
    
       this.Icon = new DrawingBrush
       {
        Drawing = new ImageDrawing
        {
         Rect = new System.Windows.Rect(0, 0, 16, 16),
         ImageSource = bmpframe
        }
       };
      }
    • Edited by Tim Lovell-Smith Wednesday, September 29, 2010 10:24 PM source code readability
    • Proposed as answer by Tim Lovell-Smith Thursday, September 30, 2010 8:50 PM
    • Marked as answer by Andrew_Zhu Tuesday, October 5, 2010 6:35 AM
    Wednesday, September 29, 2010 10:20 PM
  • Thanks for the answer.  I'll test this tomorrow.
    Thursday, September 30, 2010 9:09 PM
  • Days of searching for something that worked.  Indeed this is the only one.  Thank you 100x's!  :)
    Tuesday, February 15, 2011 7:00 PM