I created a resource in the file FrameRes.xaml
like this:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Japanese.Resources.FrameRes">
<Style x:Key="FrameBorder" TargetType="Frame">
<Setter Property="CornerRadius" Value="2" />
<Setter Property="HasShadow" Value="false" />
<Setter Property="Margin" Value="10,0" />
<Setter Property="BorderColor" Value="{DynamicResource LineColor}" />
<Setter Property="Padding" Value="0" />
<Setter Property="VerticalOptions" Value="Start" />
</Style>
</ResourceDictionary>
and this is contained inside:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:converters="clr-namespace:Japanese"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Japanese.App">
<Application.Resources>
<ResourceDictionary Source="/Resources/FooterRes.xaml" />
<ResourceDictionary Source="/Resources/FrameRes.xaml" />
</Application.Resources>
</Application>
When I try to access this in C# like this then it fails and says there's no reference to FrameBorder:
var fb2 = (Style)Application.Current.Resources["FrameBorder"];
When I try to access this in C# like this it works:
Application.Current.Resources.TryGetValue("FrameBorder", out object frameBorder);
var fb = (Style)frameBorder;
Does anyone know why the first way doesn't work. It looks the same to me.
The way you have it set up, you have a ResourceDictionary
inside another ResourceDictionary
with no key/name/reference. When you call Application.Current.Resources["FrameBorder"];
, you are accessing the upper-most level of the dictionary and looking for "FrameBorder"
, not its sub-levels. However, calling TryGetValue
goes through all levels of the Dictionary.
Read through the Docs to understand how to access values from Dictionaries.
Ok, so I have played around with the ResourceDictionary
tags and files, and I can see where you're going wrong.
According to the Xamarin Forms Docs on ResourceDictionary
, you can add stand-alone ResourceDictionary
XAML files to your App.xaml
like so:
<App ...>
<App.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</App.Resources>
...
</App>
You can replace App
with ContentPage
or ContentView
, depending on your use.
Simply put, this creates a new ResourceDictionary
object and merges other ResourceDictionary
files into it. Let's go into a bit more detail.
Let's start by looking at the Application.Current.Resources
property, which is of type ResourceDictionary
and implements ICollection
, IDictionary
, and IResourceDictionary
. Given the interfaces it implements, you can obtain the values by numeric or string ID (ex: App.Current.Resources[0]
or App.Current.Resources["LabelStyle"]
). This accesses the top-level contents of the dictionary, so only those that have been created in the <[App/ContentPage/ContentView].Resources>
tag.
You also have a property called MergedDictionaries
, which implements ICollection
. This means that you can only access the list items by numeric ID (ex: MyMergedDictionary[0]
).
When you add a ResourceDictionary
file like:
<ResourceDictionary Source="MyResourceDictionary.xaml" />
You are actually merging this file with the current ResourceDictionary
. To then access the contents of MyResourceDictionary
you would call (in C#):
App.Current.Resources.MergedDictionaries[0]["InternalKeyName"]
This is probably better explained like so:
<App ...>
<App.Resources>
<!-- Called using App.Current.Resources["PrimaryColor"] -->
<Color x:Key="PrimaryColor">#2196F3</Color>
<!-- Called using App.Current.Resources.MergedDictionaries[0]["InternalKeyName"] -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
</App.Resources>
...
</App>
In your case you have two dictionaries merged into your Application Resources: FooterRes
and FrameRes
.
For better management, I would create an enum
like:
public enum MergedResourcesEnum
{
Footer,
Frame
}
and use this enum when calling the resources in C# like so:
Application
.Current
.Resources
.MergedDictionaries[(int)MergedResourcesEnum.Frame]["FrameBorder"];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With