0

I'm working on a WinForms UI that has buttons with icons (images). Currently, I just assigned the icon image for each button using the Image property in Visual Studio designer. However, I want to be able to switch to a different set/theme of icons at runtime as well. The various methods I saw as answers on stackoverflow are specific to runtime only i.e. the code loads the respective resource assembly and then for each button loads the respective image resource and assigns it to the button. Is there an automatic way of doing this? Basically, I want to avoid coding the part where I load each resource and assign it to a specific button.

tunafish24
  • 2,288
  • 6
  • 28
  • 47

1 Answers1

1

You can use multiple ImageLists to contain your different theme images and then use those image lists as image source of your buttons for different themes. To do so:

  • Create an ImageList for each theme
  • Set Tag property of each ImageList to the theme name. (You can not access to components at run-time by name, the name property for component is only for design-time, so set the Tag property to access them by tag)
  • Set ColorDepth property to 32 bit for png images and 24 bit for bitmap images
  • Set the name for images and use the same name for same images in your different image lists, for example for image of add button in all image lists use "add" name.
  • Set the ImageList property of your buttons and also set ImageIndex or ImageKey property at design-time. Using ImageKey property is preferred because if the key is absent in ImageList it displays no image for the button.
  • Change ImageList property at run-time to get different images for your buttons.

For example you can use this code to change ImageList of all your buttons at run-time:

private IEnumerable<Control> GetAllControls(Control control)
{
    var controls = control.Controls.Cast<Control>();
    return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
}

private void ChangeTheme(string themeName)
{
    GetAllControls(this).OfType<Button>().ToList()
        .ForEach(btn =>
        {
            btn.ImageList = this.components.Components
                                .OfType<ImageList>()
                                .Where(x => Convert.ToString(x.Tag).ToLower() == themeName.ToLower())
                                .FirstOrDefault();
        });
}

And here is the usage:

this.ChangeTheme("theme1");

And it will set the image list of all buttons to an ImageList that have Tag property with value theme1.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Nice solution. Unfortunately, in my case, using imagelist makes the alpha-blended png icons looks really bad. I did setup imagelist correctly i.e. 32x32 size and 32bit color. Any ideas? – tunafish24 Oct 27 '15 at 02:28
  • Found this: http://stackoverflow.com/questions/10372797/imagelist-32-bit-images-lose-quality Unfortunately, this will result in me losing VS Designer support - which I definitely want. For my scenario, I've decided to hardcode basic theme and then use logic such as above to assign a different group of png icons to buttons at runtime. – tunafish24 Oct 27 '15 at 04:52
  • **ImageSize:** If your original images are 16x16 you should use `16,16` for `ImageSize` and don't change it to `32,32`. If you need 32x32 images, use original 16x16 images and then set `ImageSize` to `32,32`. If you set `ImageSize` to a different value that your original images sizes it will result in a very bad quality images. – Reza Aghaei Oct 27 '15 at 05:23
  • Image size is correct. Please see my second comment, it explains that ImageList control results in loss of quality and while that answer suggests a workaround, the solution results in loss of VS Designer support. – tunafish24 Oct 27 '15 at 05:29
  • **ColorDepth:** You should set `ColorDepth` to `Depth32Bit` and then add your images. – Reza Aghaei Oct 27 '15 at 05:37
  • That's what I did, the problem is with imagelist, it still screws it up. I'm marking this as the answer, since I was able to use the code you supplied and the imagelist technique could be worthwhile for people who don't have a need for alphablended icons to be displayed. – tunafish24 Oct 27 '15 at 06:15
  • Thank you for your kindly feedback :) – Reza Aghaei Oct 27 '15 at 06:20