Xamarin Forms - how to select resource in C# from MergedDictionaries

Viewed 754

Can someone show me the Linq query that would be used to select the AdjustmentsIcon style in the IconResources.xaml file below?

I know you can get to ...

Application.Current.Resources["key"]

but I am looking for a code efficient way to select out the style from the MergeDictionary using Linq.

App.xaml

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:font="clr-namespace:WP.Device.Resources"
             xmlns:resources="clr-namespace:WP.Device.Resources"
             x:Class="WP.Device.App">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <resources:IconResources />
                <resources:ColorResources />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

IconResources.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:font="clr-namespace:WP.Device.Resources"
                    xmlns:resources="clr-namespace:WP.Device.Resources"
                    x:Class="WP.Device.Resources.IconResources">
    <ResourceDictionary.MergedDictionaries>
        <resources:ColorResources />
    </ResourceDictionary.MergedDictionaries>

    <Style TargetType="Label" x:Key="AddNewIcon">
        <Setter Property="FontSize" Value="30" />
    </Style>
    <Style TargetType="Label" x:Key="AdjustmentsIcon">
        <Setter Property="FontSize" Value="40" />
    </Style>
</ResourceDictionary>

UPDATE

I appreciate @pinedax's answer, but for me...

Application.Current.Resources["key"]

doesn't have the keys from the merged dictionaries. I was not able to formulate a Linq query to find my style, but I wrote the following that works...

public Style FindStyle(ResourceDictionary resourceDictionary, string key)
{
    Style style = resourceDictionary.ContainsKey(key) ? resourceDictionary[key] as Style : null;

    if (style == null)
    {
        foreach (var mergedDictionary in resourceDictionary.MergedDictionaries)
        {
            style = FindStyle(mergedDictionary, key);

            if (style != null) break;
        }
    }
    
    return style;
}

and is called with...

Style errorIcon = FindStyle(Application.Current.Resources, "AddNewIcon");
2 Answers

I do encourage you to use the default way of fetching resources out of a ResourceDictionary as for me it is very efficient.

If you look at the ResourceDictionary source code (here) you will see there's an internal dictionary that holds all the resources keys, so when we do:

Application.Current.Resources["key"]

This is actually getting the value from that internal dictionary and dictionary lookup by key is very efficient.

But to answer your question, you should be able to get the values using Linq by using the SelectMany method on the MergeDictionaries property. Something like this:

var mergedDictionary = Application.Current.Resources.MergedDictionaries;
var resourceK = mergedDictionary.SelectMany(x => x)
                                .Where(v => v.Key == "Key")
                                .Select(t => t.Value)
                                .FirstOrDefault();

Hope this helps.-

Related