Nicolas Oñate
Nicolas Oñate

Reputation: 221

The resource is not present in the dictionary

I'm trying to get a StaticResource at code behind but when I debug just get a empty response. In my MainPage.xaml.cs I have:

public MainPage()
{
    InitializeComponent();

    /*Create buttons*/
    for (int i = 0; i < 15; i++)
    {
        FlexGrid.Add(BtnAdd(i + 1));
    }
}

private Button BtnAdd(int btnNum)
{
    Button btn = new Button();
    btn.Text = "TestButton " + btnNum;
    btn.HorizontalOptions = LayoutOptions.Center;
    btn.WidthRequest = 125;
    btn.HeightRequest = 125;
    //Here i get empty response 
    btn.BorderColor = Resources["Secondary"] as Color;
    btn.BorderWidth = 5;
    btn.Margin = new Thickness(5, 5, 5, 5);
    btn.Clicked += TestBTN;

    return btn;
}

When debug says:

System.Collections.Generic.KeyNotFoundException: 'The resource 'Secondary' is not present in the dictionary

EmptyDebug

The element is in the folder Resources/Styles/colors.xaml and is a ResourceDictionary in front i can take it just with {StaticResource Secondary}.

How can I get it at code behind?

EDIT

I find this question and I try the answers, the static class answer I don't know why I need a VisualElement and the others give me this:

var rd = App.Current.Resources.MergedDictionaries.First();

enter image description here

So now I take the Resource dictionary but with null response of each element.

Upvotes: 2

Views: 2505

Answers (2)

Serge Misnik
Serge Misnik

Reputation: 307

Surprisingly, I couldn't find a 'native' Maui solution. So I written my own recursive helper:

public static class ResourcesHelper
{
    public static bool TryGetResource<T>(this Application application, string key, out T foundItem)
    {
        foundItem = default;
        if (application is null) return false;
        if (string.IsNullOrWhiteSpace(key)) return false;
        // Find first matching resource of type T
        var found = TraverseDictionary(application.Resources, key).FirstOrDefault(pair => pair.Value is T);
        if (found.Key == null) return false;
        foundItem = (T)found.Value;
        return true;
    }

    private static IEnumerable<KeyValuePair<string, object>> TraverseDictionary(ResourceDictionary dictionary, string key)
    {
        if (dictionary is null) yield break;
        if (dictionary.TryGetValue(key, out var item))
            yield return new KeyValuePair<string, object>(key, item);
        foreach (var nextDictionary in dictionary.MergedDictionaries)
        {
            foreach (var nextPair in TraverseDictionary(nextDictionary, key))
                yield return nextPair;
        }
    }
}

Upvotes: 0

Martinedo
Martinedo

Reputation: 366

a workaround is to make a local Resource which has a BasedOn property on the global style

<ContentPage.Resources>
        <Style x:Key="button_icons_style_LOCAL" TargetType="Button" BasedOn="{x:StaticResource button_icons_style}"/>
</ContentPage.Resources>

and then to use the local one in the code.

new Button() { Style = (Style)Resources["button_icons_style_LOCAL"] }

Upvotes: 2

Related Questions