How to use a dynamic ResourceDictionary Source in Silverlight? - c#

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);

Related

How to choose a default resource dictionary for xaml in design time?

My app have 2 themes (Dark, Light), i created 2 resource dictionaries files for this.
For example:
1) Themes/Dark
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="xxx" Color="#ffffffff" />
<SolidColorBrush x:Key="xxx1" Color="#ff000000" />
</ResourceDictionary>
2) Themes/Light
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="xxx" Color="#123456" />
<SolidColorBrush x:Key="xxx1" Color="#654321" />
</ResourceDictionary>
In some view file im using this color like a:
Foreground="{DynamicResource ResourceKey=xxx}"
Before starting app i choose theme like a (abstract example):
var rootResources = Application.Current.Resources;
var resDict = new ResourceDictionary () {
Source = new Uri (path, UriKind.RelativeOrAbsolute)
};
rootResources.MergedDictionaries.Add (resDict);
But in design time in Designer my resource dictionary is not chosen, and i have this problem (screen):
Click
How i can choose resource dictionary for design time?
Added this code to csproj file not working for me
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
...Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND...

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.

Is it possible to have a static list of Styles in Xaml

I would like to have a static list of Styles in Xaml
So far I have tried:
<local:Styles xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp.Core;assembly=MyApp.Core">
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="TextColor" Value="Green" />
</Style>
</local:Styles>
Code Behind
public partial class Styles : List<Style>
{
public Styles()
{
}
}
but when I do
var styles = new Styles();
The class is empty.
As an aside I can't use Application Resources or ResourceDictionary
You can place your styles in a ResourceDictionary (Add -> New Item -> Resource Dictionary):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Your styles here -->
<Style ...
</ResourceDictionary>
Don't forget that you will need to add a reference to it in App.xaml:
<Application x:Class="Your.App.Namespace"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Your.App.Namespace;component/Path/To/Dictionary.xaml"/>
...
To get hold of these styles in code-behind, you can use the FindResource method:
Style myStyle = App.Current.FindResource("MyStyleKey") as Style;
One additional Idea that comes to mind
Create a standard Xamarin.Forms.Solution
Mark up the Application XAML with your Styles
Instantiate it and Serialize the Application.Resource to XML
Go back to your MVVMCross app and deserialize it on load and assign it to each page at construction or Application.Current.Resources. Once you have the format for the XML you'd be able to edit it directly and it would be portable from project to project basically a css style sheet(in xml format) for Xamarin Forms might be fun.

Changing resource in the runtime

Let's suppose, that we've got the following dictionary:
<ResourceDictionary xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String x:Key="Test">Ala ma kota</sys:String>
</ResourceDictionary>
This dictionary is merged somewhere in custom control:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
How can I completely change value of the resource "Test" during application runtime from the code behind?
You can change resource from code-behind but main thing is how you are binding to that resource i.e. via StaticResource or DynamicResource.
Modify like this -
Resources["Test"] = "Ala ma kota updated";
XAML (After resource update from code behind, text value will differ for two approaches) -
<TextBlock Text="{StaticResource Test}"/> // Will be Ala ma kota
<TextBlock Text="{DynamicResource Test}"/> // Will be Ala ma kota updated
If you are looking to change a resource from code behind then just access the resource like a dictionary and change desired value :)
Like this:
this.Resource["myThickness"] = new Thickness(2);
That would be it :)

WPF localization with ResourceDictionary

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

Categories