Share via


Windows forms access resources by name

Introduction

When items from a project resource is needed like a bitmap, Icon etc. the following can will retrieve the resource, in this case an Icon.

Icon chatIcon = Properties.Resources.Chat;


Then there are cases were a requirement specifies a resource item is needed by the resource name, learn how to get resources by name for either an icon or bitmap along with sizing a PictureBox to properly display the image. By examining the code presented other resource types like documents of various types may be read from resources and used.

Container

This class provides properties for resource name, the image and if the image is a Icon or BitMap.

public class  ResourceItem
{
    /// <summary>
    /// Resource name
    /// </summary>
    public string  Name { get; set; }
    /// <summary>
    /// Image which is either an icon or bitmap
    /// </summary>
    public Bitmap Image { get; set; }
    /// <summary>
    /// Indicates if dealing with an icon so when displaying the
    /// control used to display can adjust it's size or Size mode
    /// </summary>
    public bool  IsIcon { get; set; }
    public override  string ToString() => Name;
}

Class to read resources

The following class provides 

  • A method to obtain resource names
  • A method to read resources into a list
namespace ChangeImage.Classes
{
    /// <summary>
    /// Read images from current project resources
    /// </summary>
    public class  ImageHelper
    {
 
        /// <summary>
        /// Get all bitmap and icon resources
        /// </summary>
        /// <returns></returns>
        public static  List<ResourceItem> ResourceItemList()
        {
            var items = new  List<ResourceItem>();
 
            foreach (var name in ResourceImageNames())
            {
                /*
                 * For this code sample ignore the default image
                 */
                if (name == "ready")
                {
                    continue;
                }
                 
                var item = new  ResourceItem() {Name = name, IsIcon = false};
                 
                if (Resources.ResourceManager.GetObject(name) is Icon)
                {
                    item.Image  = ((Icon)Resources.ResourceManager.GetObject(name))?.ToBitmap();
                    item.IsIcon = true;
                }
                else
                {
                    item.Image = (Bitmap)Resources.ResourceManager.GetObject(name);
                }
                 
                items.Add(item);
 
 
            }
 
            return items;
             
        }
        /// <summary>
        /// Get all resource names for icon and bitmaps
        /// </summary>
        /// <returns></returns>
        public static  List<string> ResourceImageNames()
        {
 
            try
            {
                 
                var names = new  List<string>();
                 
                var resourceSet = Resources
                    .ResourceManager
                    .GetResourceSet(CultureInfo.CurrentUICulture, true, true);
                 
                names.AddRange(
                    from DictionaryEntry dictionaryEntry in  resourceSet 
                    where dictionaryEntry.Value is  Image || dictionaryEntry.Value is Icon 
                    select dictionaryEntry.Key.ToString());
                 
                return names;
                 
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
}

Main access

The following singleton class provides access to resource images read once on the first time a call is made to Instance.Images.

namespace ChangeImage.Classes
{
    /// <summary>
    /// Provides access to resource images by loading them once
    /// </summary>
    public sealed  class ResourceImages
    {
        private static  readonly Lazy<ResourceImages> Lazy =
            new Lazy<ResourceImages>(() => new ResourceImages());
 
        public static  ResourceImages Instance => Lazy.Value;
 
        private List<ResourceItem> _images;
        /// <summary>
        /// Get all icon and bitmap images from project resources
        /// </summary>
        /// <returns>list of images</returns>
        public List<ResourceItem> Images() => _images ??= ImageHelper.ResourceItemList();
    }
}

Extension methods

Use these extension methods to get only Icon or BitMap images from resources read from ImageHelpers.ResourceList called from ResourceImages.Instance.Images.

namespace ChangeImage.Extensions
{
    public static  class ResourceItemExtensions
    {
        /// <summary>
        /// Return resources of type Icon
        /// </summary>
        /// <param name="sender"></param>
        /// <returns>list of icons or an empty list</returns>
        public static  List<ResourceItem> Icons(this List<ResourceItem> sender) => 
            sender.Where(item => item.IsIcon).ToList();
        /// <summary>
        /// Return resources of type Bitmap
        /// </summary>
        /// <param name="sender"></param>
        /// <returns>list of bitmaps or an empty list</returns>        
        public static  List<ResourceItem> BitMaps(this List<ResourceItem> sender) => 
            sender.Where(item => !item.IsIcon).ToList();
    }
}

Example usage

A form is setup with three ListBox controls to display images while the topmost ListBox has a button associated to display images in a PictureBox while the other two are showing icon and bitmap images to demonstrate the  two language extensions above. Note the method ChangeFromAllImages method would normally be in the button click which would made it difficult (would need to use PerformClick for that button) to display the first image on form shown event.

using System;
using System.Windows.Forms;
using ChangeImage.Classes;
using ChangeImage.Extensions;
 
namespace ChangeImage
{
    public partial  class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
             
            Shown += OnShown;
        }
 
        private void  OnShown(object? sender, EventArgs e)
        {
            var allImages = ResourceImages.Instance.Images();
             
            /*
             * Do we have images from resources?
             */
            if (allImages is null)
            {
                MessageBox.Show("No images located");
                SelectFromAllImagesButton.Enabled = false;
            }
             
            AllImagesListBox.DataSource = allImages;
 
            ChangeFromAllImage();
 
            IconListBox.DataSource = allImages.Icons();
 
            BitmapListBox.DataSource = allImages.BitMaps();
        }
 
        private void  SelectFromAllImagesButton_Click(object sender, EventArgs e)
        {
            ChangeFromAllImage();
        }
 
        private void  ChangeFromAllImage()
        {
            if (AllImagesListBox.SelectedIndex <= -1) return;
 
            var item = (ResourceItem) AllImagesListBox.SelectedItem;
            pictureBox1.SizeMode = item.IsIcon ? PictureBoxSizeMode.Normal : PictureBoxSizeMode.Zoom;
            pictureBox1.Image = item.Image;
        }
    }
}

Summary

Code presented provides access to resources in a Windows form project.

Using in a project

  • Copy classes under the classes folder, change the namespace to match the current project.
  • Copy the class under Extensions, change the namespace to match the current project.
  • Use the code in the form to implement

Source code

Clone this GitHub repository in Visual Studio or with Git Desktop.

See also

Localization for Windows Universal apps
String and Embedded Resources inside Windows Store App
Windows forms overview
C# Singletons