Resource Dictionaries enables us to create reusable resources in our XAML files or in code behind! To resolve and access Resource Dictionary Resources in code behind, we can access it, in some cases, by using the Resource Key index name in the Resource Dictionary:

var cornerRadius = Application.Current?.Resources["DefaultCornerRadius"] as CornerRadius;

…or with TryGetValue

if (Application.Current?.Resources.TryGetValue("DefaultCornerRadius", out var resource) ?? false)
{
  var cornerRadius = resource as CornerRadius;
}

BUT when we need to access a Resource that is defined with OnPlatform, OnIdiom and/or references a DynamicResource in a Merged Dictionary, it gets trickier! Especially if this is nested in multiple layers!

Let’s look at an extreme example!

First we have the main Application Resource Dictionary with the DefaultCornerRadiusresource. Based OnPlatform the value references a specific DynamicResource.

<Application.Resources>
    <ResourceDictionary>
        <OnPlatform x:Key="DefaultCornerRadius" x:TypeArguments="CornerRadius">
            <On Platform="Android" Value="{DynamicResource SmallCornerRadius}"/>
            <On Platform="iOS"  Value="{DynamicResource MediumCornerRadius}/>
        </OnPlatform>
    </ResourceDictionary>
</Application.Resources>

At runtime, the DefaultStyle Resource Dictionary is added, based on screen resolution, as a Merged Dictionary with the values for CornerRadius.

Resources.MergedDictionaries.Add(new DefaultStyle());

In DefaultStyle dictionary, both SmallCornerRadius and MediumCornerRadius is defined based on Idiom!

<ResourceDictionary
    x:Class="RetailOperationApp.Resources.Styles.DefaultStyle"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <OnIdiom
        x:Key="SmallCornerRadius"
        x:TypeArguments="CornerRadius"
        Default="10"
        Desktop="11"
        Phone="12"
        TV="13"
        Tablet="14"
        Watch="15" />

    <OnIdiom
        x:Key="MediumCornerRadius"
        x:TypeArguments="CornerRadius"
        Default="20"
        Desktop="21"
        Phone="22"
        TV="23"
        Tablet="24"
        Watch="25" />
        
</ResourceDictionary>

In this case and as far as I know, to resolve the correct CornerRadius for DefaultCornerRadius requires first resolving the correct OnPlatform, then finding the DynamicResource and finally resolve the correct OnIdom…which makes it tricky to have a easy way of resolving ANY resource!

BUT, what if we could resolve ANY resource like this:

var cornerRadius = ResourcesUtility.FindResource<CornerRadius>("DefaultCornerRadius");

…or…

var cornerRadius = Application.Current?.Resources.FindResource<CornerRadius>("DefaultCornerRadius");

To solve this, I have made the following static class that enables just that!

public static class ResourcesUtility
{
    private static T? GetResource<T>(ResourceDictionary resources, object? resource)
    {
        //Check resource type
        switch (resource)
        {
            case OnPlatform<T> value:
                //Get return type platform specific resource
                return GetResource<T>(resources, value.Platforms?.FirstOrDefault(p => p.Platform.Contains($"{DeviceInfo.Platform}"))?.Value);

            case OnIdiomExtension value:
                {
                    //Get idiom specific resource
                    var idiomValue = value.Default;
                    if (DeviceInfo.Idiom == DeviceIdiom.Desktop) idiomValue = value.Desktop;
                    if (DeviceInfo.Idiom == DeviceIdiom.Phone) idiomValue = value.Phone;
                    if (DeviceInfo.Idiom == DeviceIdiom.Tablet) idiomValue = value.Tablet;
                    if (DeviceInfo.Idiom == DeviceIdiom.TV) idiomValue = value.TV;
                    if (DeviceInfo.Idiom == DeviceIdiom.Watch) idiomValue = value.Watch;
                    return GetResource<T>(resources, idiomValue);
                }

            case OnIdiom<T> value:
                {
                    //Get return type idiom specific resource
                    var idiomValue = value.Default;
                    if (DeviceInfo.Idiom == DeviceIdiom.Desktop) idiomValue = value.Desktop;
                    if (DeviceInfo.Idiom == DeviceIdiom.Phone) idiomValue = value.Phone;
                    if (DeviceInfo.Idiom == DeviceIdiom.Tablet) idiomValue = value.Tablet;
                    if (DeviceInfo.Idiom == DeviceIdiom.TV) idiomValue = value.TV;
                    if (DeviceInfo.Idiom == DeviceIdiom.Watch) idiomValue = value.Watch;
                    return idiomValue;
                }

            case DynamicResource value:
                //Get dynamic resource
                return resources.FindResource<T>(value.Key);

            case string value:
                {
                    //Attempt to cast to resource type or return default
                    try
                    {
                        var converter = TypeDescriptor.GetConverter(typeof(T));
                        if (converter?.CanConvertFrom(typeof(string)) ?? false)
                        {
                            // Cast ConvertFromString(string text) : object to (T)
                            return (T?)converter.ConvertFromString(value);
                        }
                        return default;
                    }
                    catch
                    {
                        return default;
                    }
                }

            case T value:
                //Return found resource value
                return value;

            default:
                //Return default resource value
                return default;
        }
    }

    public static T? FindResource<T>(this ResourceDictionary resources, string resourceKey)
    {
        //Verify parameter
        if (string.IsNullOrWhiteSpace(resourceKey))
            return default;

        //Attempt to find resource
        if (resources.TryGetValue(resourceKey, out var resource))
            //Get resource
            return GetResource<T>(resources, resource);
        else
            //If nothing found, return default
            return default;
    }

    public static T? FindResource<T>(string resourceKey)
    {
        //Verify Current Application
        if (Application.Current is not null)
            //Attempt to find resource
            return Application.Current.Resources.FindResource<T>(resourceKey);
        else
            //If nothing found, return default
            return default;
    }
}

So with this we have a easy way to “Get ANY Resource Dictionary Value in Code Behind”. Enjoy!