WPF localization with ResourceDictionary - c#

At the moment I integrate the current strings like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="lang/Dictionary.en-US.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Is there a possibility to do this dynamically in my code behind files?

Sure you can just do something like:
var res = new ResourceDictionary {Source = new Uri("somepath")};
this.Resources.MergedDictionaries.Add(res);
Note: This is off the top of my head on not tested but it should work

Related

Xamarin.Forms MergedDictionaries

I have created few XAML styles and added them all into App.xaml.cs as MergedDictionaries
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Axon.Mobile.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionaries/Colors.xaml"/>
<ResourceDictionary Source="ResourceDictionaries/GlobalStylesDictionary.xaml"/>
<ResourceDictionary Source="ResourceDictionaries/KeyStylesDictionary.xaml"/>
<ResourceDictionary Source="ResourceDictionaries/ReceptionStylesDictionary.xaml"/>
<ResourceDictionary Source="ResourceDictionaries/PutAwayStylesDictionary.xaml"/>
<ResourceDictionary Source="ResourceDictionaries/ViewModelLocatorDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
This soolution is working when I use style defined in any dictionary as StatisResouce i.e:
<Label TextColor="{StaticResource Test1}"/>
However I would like to create dynamic resources and in that case I need to replace the styles in C#. The problem is that
Application.Current.Resources
contains these 6 another dictionaries as MergedDictionary property. All of given dictionaries are empty.
Why can't I get the defined styles in C#?
That's strange but I've noticed that we can only access resources located in MergedDictionaries using the TryGetValue method for the moment:
if (Application.Current.Resources.TryGetValue("StyleResourceKey", out var objectStyle))
{
var style = (Style)objectStyle;
//Edit your style
}

Nesting ResourceDictionaries with MergedDictionaries in UWP

I'm trying to split up a ResourceDictionary containing styles for multiple controls in our current UWP application. The file has grown to about 3000 lines and has become a living hell to manage, so I decided to split it up into smaller, more specific ResourceDictionaries and include them using MergedDictionaries.
App.xaml
<common:BootStrapper x:Class="Asteria.Ion.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:Template10.Common"
xmlns:styles="using:Asteria.Ion.Styles"
RequestedTheme="Dark">
<common:BootStrapper.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles\Custom.xaml" />
<ResourceDictionary Source="Styles\CustomControls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</common:BootStrapper.Resources>
</common:BootStrapper>
CustomControls.xaml contains references to other ResourceDictionaries.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Template10.Controls"
xmlns:behaviors="using:Template10.Behaviors"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:local="using:Asteria.Ion.Styles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
<ResourceDictionary Source="Templates.xaml" />
<ResourceDictionary Source="ComponentBlock.xaml" />
<ResourceDictionary Source="FlowAgent.xaml" />
<ResourceDictionary Source="Planning.xaml" />
<ResourceDictionary Source="ProjectDialog.xaml" />
<ResourceDictionary Source="Inspector.xaml" /-->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
This will always produce the following exception:
Failed to assign to property 'Windows.UI.Xaml.ResourceDictionary.Source' because the type 'Windows.Foundation.String' cannot be assigned to the type 'Windows.Foundation.Uri'. [Line: 12 Position: 37]
I've tried changing the source URI numerous times, but it keeps giving this error. Only commenting out all the ResourceDictionary elements in CustomControls.xaml helps. But then I get exceptions concerning missing styles of course.
Some URI formats I've tried:
/Styles/Shared.xaml
Styles/Shared.xaml
Styles\Shared.xaml
.\Shared.xaml
ms-appx:///Styles/Shared.xaml
None of them work.
Any advice would be appreciated.
In the end it had nothing to do with the URI structure, but with a combination of ThemeDictionaries and MergedDictionaries.
What was working before:
In App.Resources:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/Themes.xaml" />
<ResourceDictionary Source="Styles/CustomControls.xaml" />
</ResourceDictionary.MergedDictionaries>
Where Themes.xaml contained ThemeDictionaries and CustomControls.xaml contained <Styles> ( a lot of them ).
After splitting CustomControls.xaml, it no longer contained any styles, but only MergedDictionaries.
Looking something like this:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ControlStyles/ProjectDialog.xaml" />
<ResourceDictionary Source="ControlStyles/Inspector.xaml" />
</ResourceDictionary.MergedDictionaries>
Inspector.xaml contained a Style using {ThemeResource} and it appears that's where it went wrong. The solution/work-around in the end was to include a MergedDictionaries with a references to Themes.xaml in Inspector.xaml.
Now if anyone can explain the exact reasoning behind this solution, I'd be much obliged.
From the error message,XAML Compiler failed to translate the Source Property of nested ResourceDictionaries. The easiest and fastest workaround is to add the nested ResourceDictionaries in App.Xaml.cs:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
...
var applicationMergedDics = Application.Current.Resources.MergedDictionaries;
applicationMergedDics[0].MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ms-appx:///Styles/Shared.xaml") });
applicationMergedDics[0].MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ms-appx:///Styles/Templates.xaml") });
...
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
Notes: Don't forget to remove the MergedDictionaries in CustomControls.xaml. And the error will be gone.

WPF Cannot locate resource

I have a resource file and two views. This views use a resource file
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
And it will work while i dont put one view to the another. In this case i get this error
Cannot locate resource 'dictionary1.xaml'
How to fix it?
Use Pack Uri's
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Assembly_Name;component/Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
If Dictionary1.xaml in your project's rootpath, remove '/' before Dictionary1
<ResourceDictionary Source="Dictionary1.xaml"/>
Or you can use packuri like :
/yourAssemblyName;component/Dictionary1.xaml

Merge DictionaryResource from Application in a ClassLibrary

I have a Windows Phone 8.1 solution that has a Standard Application Project and a Class Library Project. The idea is that I can, somehow, StaticResources down do the ClassLibrary so it can override the existing ones. I'll give you an example:
In my ClassLibrary I have a ClassLibraryDictionary.xaml with the following code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ClassLibraryTest">
<SolidColorBrush x:Key="MyButtonColor" Color="#FF0000FF" />
</ResourceDictionary>
And the idea is that in my MainApplication I could have a Dictionary.xaml with the same StaticResource Key, and pass it to my ClassLibrary so it can override the default property, something like:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MainApplicationTest">
<SolidColorBrush x:Key="MyButtonColor" Color="#00FF00FF" />
</ResourceDictionary>
And passing it in code:
var mainAppDictionary = new ResourceDictionary();
mainAppDictionary.Source = new Uri("/using:MainApplicationTest;component/MainApplicationDictionary.xaml", UriKind.RelativeOrAbsolute);
classLibraryTest.SetResourceDictionary(mainAppDictionary);
The problem here is that I can't seem to use the ResourceDictionary instance in my ClassLibrary, and I'm not even sure this is the best way to do this.
So, how could I solve this?
I found out how to this and it is actually simple. The path I was using was not the correct one, so to sum it all up, the solution in XAML, if you were to do it in the App.xaml (in the MainApp) looks like this:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx://Common/yourclasslibraryname/ClassLibraryDictionary.xaml"></ResourceDictionary>
<ResourceDictionary Source="/Dictionary1.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
If you want to set it in code directly in the ClassLibrary you can do something like this:
In the MainApp.xaml.cs
myClassLibrary.MergeAllDictionaries(App.Current.Resources);
And in the ClassLibrary:
public void MergeAllDictionaries(ResourceDictionary appDictionary) {
// First copy all keys from MainApp to a new Dictionary
ResourceDictionary mainDictionary = new ResourceDictionary();
foreach(var keys in appDictionary.MergedDictionaries) {
foreach(var keys1 in keys) {
mainDictionary.Add(keys1.Key, keys1.Value);
}
}
// Then clear all
appDictionary.Clear();
// Get the ClassLibrary dictionary
ResourceDictionary classLibraryDictionary = new ResourceDictionary();
classLibraryDictionary.Source = new Uri("ms-appx://Common/yourclasslibraryname/ClassLibraryDictionary.xaml", UriKind.RelativeOrAbsolute);
// First add the ClassLibrary keys and values
appDictionary.MergedDictionaries.Add(classLibraryDictionary);
// Then add the old values, so that they overwrite the ClassLibrary ones
appDictionary.MergedDictionaries.Add(mainDictionary);
}

How to use a dynamic ResourceDictionary Source in Silverlight?

How to use a dynamic ResourceDictionary Source in Silverlight? My app has one "Styles.xaml" with a lot of style definitions and references a "Colors.xaml" where a couple of brushes are defined:
Styles.xaml:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Project;component/Colors.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="MyLayoutTemplate">
<Button Background="ButtonBackgroundBrush">Button Title</Button>
</DataTemplate>
<!-- A lot of other definitions -->
</ResourceDictionary>
Colors.xaml:
<ResourceDictionary>
<SolidColorBrush x:Key="ButtonBackgroundBrush" Color="#FFFFFFFF"/>
<!-- ... -->
</ResourceDictionary>
So basically the Styles.xaml defines the layout and Colors.xaml defines the colors (duh). My App.xaml ONLY references this Styles.xaml.
What I need is a way to do not use this:
<ResourceDictionary Source="/Project;component/Colors.xaml" />
And "point" (or bind) this Source property to a static class where this will be defined dynamically. Something like this:
<ResourceDictionary Source="{Binding Settings.ThemeUri}" />
Is there any way to achieve this?
You can really achieve this in XAML only, but it is simple to create the dictionaries in code.
ResourceDictionary styleDictionary = new ResourceDictionary()
{
Source = new Uri("/Project;component/Styles.xaml", UriKind.Absolute)
};
ResourceDictionary colorDictionary = new ResourceDictionary()
{
Source = new Uri("/Project;component/Colors.xaml", UriKind.Absolute)
};
styleDictionary.MergedDictionaries.Add(colorDictionary);
Application.Current.Resources.MergedDictionaries.Add(styleDictionary);

Categories