DEV Community

Cover image for Images from a Windows Form project resource
Karen Payne
Karen Payne

Posted on

Images from a Windows Form project resource

With modern technologies such as MAUI for desktop solutions there is still a place for Windows Form projects from new developers just starting out to quickly building internal utility projects.

In this article learn how to show images from a project’s resources in a windows form working with .NET Core 7 Window Forms and a .NET Core 7 class project (optional).

sample display

Source code

Clone the following GitHub repository.

Note
I've seen this question pop-up on various forms over the past 20 years and this is one reason for this article.

Let's begin

Although the code could be completely written in a single form which means to use said code in another project the developer must pick through the code, copy and paste into another project. There is a project done this way while another project uses a class project for base code to read images from the calling project resources.

Feel free to examine code for the project ChangeImage were all need code is in the project.

We will focus on using a class project, ResourceLibrary.

The model for storing resource information.

public class ResourceItem
{
    /// <summary>
    /// Resource name
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// Image which is either an <see cref="Icon"/> or <see cref="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;
}
Enter fullscreen mode Exit fullscreen mode

The following class reads images of type Icon and Bitmap

using System.Collections;
using System.Drawing;
using System.Globalization;
using System.Resources;
using ResourceLibrary.Models;

namespace ResourceLibrary;

public class ImageHelper
{
    public static List<string> ResourceImageNames(ResourceManager manager)
    {

        var names = new List<string>();
        var resourceSet = manager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);

        names.AddRange(resourceSet!.Cast<DictionaryEntry>()
            .Where(dictionaryEntry => dictionaryEntry.Value is Image || 
                                      dictionaryEntry.Value is Icon)
            .Select(dictionaryEntry => dictionaryEntry.Key.ToString()));

        return names;
    }


    /// <summary>
    /// Get all bitmap and icon resources
    /// </summary>
    /// <returns></returns>
    public static List<ResourceItem> ResourceItemList(ResourceManager manager)
    {
        var items = new List<ResourceItem>();

        foreach (var name in ResourceImageNames(manager))
        {

            var item = new ResourceItem()
            {
                Name = name, 
                IsIcon = false
            };

            if (manager!.GetObject(name) is Icon)
            {
                item.Image = ((Icon)manager.GetObject(name)!)?.ToBitmap();
                item.IsIcon = true;
            }
            else
            {
                item.Image = (Bitmap)manager.GetObject(name)!;
            }

            items.Add(item);

        }

        return items;

    }
}

Enter fullscreen mode Exit fullscreen mode

Next, several language extensions which filter all resource list to a specific type.

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();
}
Enter fullscreen mode Exit fullscreen mode

In a forms project, add a ListBox and PictureBox with the PictureBox large enough to all all images to be displayed. Later in code there is a method to adjust the PictureBox SizeMode.

Add a reference to the class project.

Add the following class which can be used in other projects.

public sealed class ResourceImages
{
    private static readonly Lazy<ResourceImages> Lazy 
        = new(() => new());

    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(
            Properties.Resources.ResourceManager);
        return _images;
    }
}
Enter fullscreen mode Exit fullscreen mode

To display all images, add a BindingSource to the form.

private readonly BindingSource _allBindingSource = new ();
Enter fullscreen mode Exit fullscreen mode

In Form OnShown event, add the following code to get all images.

_allBindingSource.DataSource = ResourceImages.Instance
    .Images()
    .OrderBy(x => x.Name)
    .ToList();
Enter fullscreen mode Exit fullscreen mode

Add the following method to the form for displaying the current image when the user changes the selected item in the ListBox.

private void ChangeFromAllImage()
{
    if (AllImagesListBox.SelectedIndex <= -1) return;

    var item = (ResourceItem) _allBindingSource.Current;
    AllImagesPictureBox.SizeMode = item!.IsIcon ? PictureBoxSizeMode.Normal : PictureBoxSizeMode.Zoom;
    AllImagesPictureBox.Image = item.Image;
}
Enter fullscreen mode Exit fullscreen mode

And,

private void BitmapBindingSource_PositionChanged(object? sender, EventArgs e)
{
    ChangeFromBitmapImage();
}
Enter fullscreen mode Exit fullscreen mode

Back to OnShown event, add the following lines which

  • Displays the image names in the ListBox as ResourceItem overrides ToString which the ListBox uses for DisplayMember.

  • Subscribes to OnPosition changed which called ChangeFromAlImages which in turn displays the appropriate image.

        AllImagesListBox.DataSource = _allBindingSource;
        _allBindingSource.PositionChanged += AllBindingSource_PositionChanged;

        ChangeFromAllImage();
Enter fullscreen mode Exit fullscreen mode

Caveat

Suppose there is a need to display a specific image? Although a BindingSource has a Find method, it is not supported for a list. The work around is to use a BindingList which is populated with the images via

_bindingList = new BindingList<ResourceItem>(ResourceImages.Instance
    .Images()
    .BitMaps()
    .OrderBy(x => x.Name)
    .ToList());
Enter fullscreen mode Exit fullscreen mode

Setup as before but with the BindingList

_bitmapBindingSource.DataSource = _bindingList;
BitmapImagesListBox.DataSource = _bitmapBindingSource;
Enter fullscreen mode Exit fullscreen mode

Now to find a specific image.

var resourceItem =_bindingList.FirstOrDefault(x => x.Name == "Miata2");
if (resourceItem != null) _bitmapBindingSource.Position = 
    _bitmapBindingSource.IndexOf(resourceItem);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)