Simple Usage of Bitmaps in WPF XAML - CodeProject

:

Introduction

If you need to make an application which uses many non vector graphics (button or menu icons, window icons), it is difficult to use 'pack' syntax, it makes the code difficult and big. Of course, there are some workarounds with using static keys, but they are all too complicated. I think I have a good and convenient solution...

I will not show examples of difficult usage, you can find them on the internet, or maybe you use them just always. Just a solution...

Using the Code

All that we need is to create a resource assembly and write a simple markup extension R:

[ContentProperty("ResourceKey")]
[MarkupExtensionReturnType(typeof(ImageSource))]
public class R : MarkupExtension
{
    /// <summary>
    /// Resource key
    /// </summary>
    public String ResourceKey { get; set; }

    /// <summary>
    /// Property to override resource if it was get haghter
    /// </summary>
    public Object Resource { get; set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="R"/> class.
    /// </summary>
    /// <param name="resourceKey">
    /// The resource key to use to obtain the localized value.</param>
    public R(string resourceKey)
    {
        ResourceKey = resourceKey;
        Resource = TryGetImageSource(resourceKey);
    }

    private static readonly Dictionary<String, 
    	ImageSource> _imagesSources = new Dictionary<string, ImageSource>();

    public static ImageSource TryGetImageSource(String resourceKey)
    {
        ImageSource result;
        if (_imagesSources.TryGetValue(resourceKey, out result))
        {
            return result;
        }

        try
        {
            result = new BitmapImage(new Uri
            (@"pack://application:,,,/BitmapResources;component/Resources/{0}.png".F(resourceKey)));
        }
        catch
        {
            try
            {
                result = new BitmapImage(new Uri
                (@"pack://application:,,,/BitmapResources;component/Resources/{0}.ico".F(resourceKey)));
            }
            catch
            {
                try
                {
                    result = new BitmapImage(new Uri
                   	(@"pack://application:,,,/BitmapResources;component/Resources/{0}.jpg".F(resourceKey)));
                }
                catch
                {
                    //Here you can implement retrieving any other extensions
                }
            }
        }
        if (result != null)
        {
            result.Freeze();
            _imagesSources[resourceKey] = result;
        }
        return result;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return Resource;
    }
}

Please look carefully to pack paths specified in code:

pack://application:,,,/BitmapResources;component/Resources/{0}.png

Here BitmapResources is the name of DLL with resources.

DLL with resources contain folder Resources with 2 images:

https://www.codeproject.com/KB/WPF/890213/BitmapResourcesProject.png

You should add images and specify build action for them as 'Resource'.

Then, you can use new extension in your WPF project:

<Window x:Class="WPFBitmapResources.MainWindow"

        xmlns:r="clr-namespace:BitmapResources;assembly=BitmapResources"

        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Image Source="{r:R A}" Width="50" Height="50"/>
        <Image Source="{r:R B}" Width="50" Height="50"/>
        <Image Source="{r:R A}" Width="100" Height="100"/>
        <Image Source="{r:R B}" Width="100" Height="100"/>
    </StackPanel>
</Window>

Final look in designer:

https://www.codeproject.com/KB/WPF/890213/FinalDesignerLook.PNG

Done!

Points of Interest

Using the same technique, it is simple to use String resources or make localizable project.

History