Changing the Theme at Run Time - c#

I use JetPack theme and set it from App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/Styles/Brushes.xaml"/>
<ResourceDictionary Source="Assets/Styles/Fonts.xaml"/>
<ResourceDictionary Source="Assets/Styles/CoreStyles.xaml"/>
<ResourceDictionary Source="Assets/Styles/Styles.xaml"/>
<ResourceDictionary Source="Assets/Styles/SdkStyles.xaml"/>
<ResourceDictionary Source="Assets/Styles/ToolkitStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
How can i set theme from code-behind and change theme at run time?

The Silverlight Toolkit base Theme control provides support for changing a theme at runtime. Unfortunately, the Application Themes like the JetPack Theme are no Toolkit themes (ask Microsoft why). So you'd have to convert them yourself. A look at the Toolkit themes sources helps us to figure out how:
public class JetPackTheme : Theme
{
private static Uri ThemeResourceUri = new Uri("/MyComponent;component/JetPackTheme.xaml", UriKind.Relative);
public JetPackTheme() : base(ThemeResourceUri) { }
public static bool GetIsApplicationTheme(Application app)
{
return GetApplicationThemeUri(app) == ThemeResourceUri;
}
public static void SetIsApplicationTheme(Application app, bool value)
{
SetApplicationThemeUri(app, ThemeResourceUri);
}
}
Now, assuming your resources are in a folder called JetPackTheme, here is JetPackTheme.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/Brushes.xaml"/>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/Fonts.xaml"/>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/CoreStyles.xaml"/>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/Styles.xaml"/>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/SdkStyles.xaml"/>
<ResourceDictionary Source="/MyComponent;component/JetPackTheme/ToolkitStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Now you should be able to use a JetPackTheme control in your application:
<myCmp:JetPackTheme x:Name="myTheme">
<SomeNeatStuff>
...
</SomeNeatStuff>
</myCmp:JetPackTheme>
To change the theme at runtime, you can simply do
myTheme.ThemeUri = new Uri("Path/To/The/Theme.xaml", UriKind.RelativeOrAbsoluteOrWhatever);

Related

WPF application can not open by file associate

I have an WPF application, i using caliburn micro library for MVVM.
public class AppBootstrapper : BootstrapperBase{
protected override void OnStartup(object sender, StartupEventArgs eventArgs)
{
LoadUserConfigData();
if (eventArgs.Args.Count() != 0)
{
MessageBox.Show(eventArgs.Args[0]);
}
else
{
MessageBox.Show("no");
}
StartProgram();
}
}
here is my xaml
<Application x:Class="Mat.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Mat">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:AppBootstrapper x:Key="bootstrapper" />
</ResourceDictionary>
<ResourceDictionary Source="/UIStyle;component/UIStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I using NSIS for creating installer exe file, and i register file associate by NSIS script.
but when i double click on file nothing happen excepted the cursor is loading.
many thanks for your suggest.
i follow #krzysztof skowronek direction, i attach my app process to Visual studio, and debug. the reason it doesn't launch is it got exception that wasn't handled (logged).

Resource Dictionary for DLL in C# WPF

Is there a way to load a resource dictionary once for a DLL and use it in all controls? I tried creating an application in the DLL that contains only the resource dictionary. This, unsurprisingly, does not work.
After fixing an issue with Build Action, this throws an exception on creating multiple applications.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary Source="pack://application:,,,/HelperWPF;component/Display/DefaultDictionary.xaml"/>
</Application.Resources>
</Application>
I was able to use the same instance of a resource dictionary by making the following static class:
internal static class LoadResourceDictionary
{
static LoadResourceDictionary()
{
resourceDictionary = Application.LoadComponent(new Uri("/DllName;component/Shared/ReusedDictionary.xaml",UriKind.RelativeOrAbsolute)) as ResourceDictionary;
}
public static ResourceDictionary resourceDictionary;
}
Then referencing it in the class
public SingleAlarm_UC()
{
this.Resources = LoadResourceDictionary.resourceDictionary;
InitializeComponent();
}
You need the MergedDictionaries tag even if it is only a single ResourceDictionary
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/App.Resources;component/Styles/Brushes.xaml" />
<ResourceDictionary Source="pack://application:,,,/App.Resources;component/Styles/Fonts.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Also something I have found is it does not work if you use a merged dictionary in the Resources assembly. You need to reference each individually

WPF – Insert Resource Dictionary in C# into XAML

By this way I can access XAML resources in C# code:
var resource = new ResourceDictionary
{
Source = new Uri("/myAssemblyName;component/Themes/MyStyle.xaml", UriKind.RelativeOrAbsolute)
};
I thinking about a reverse approach. I would like define resource dictionary in C# code like this:
public class MyColors : ResourceDictionary
{
public MyColors ()
{
this.Add("MyGreen", Color.FromRgb(10, 211, 12)); // this["MyGreen"] = Color.FromRgb(10, 211, 12);
}
}
And then include this resource dictionary into XAML style file like this:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyColors.cs" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="MyGreenBrush" Color="{StaticResource MyGreen}" />
</ResourceDictionary>
The question is about possibility of including resource dictionary into XAML file. Because presented approach not working – error: Unexpected project file type at …\MyColors.cs.
You need to construct your created class inside MergedDictionaries
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<yourClassXmlNamespace:MyColors/>
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="MyGreenBrush" Color="{StaticResource MyGreen}" />
</ResourceDictionary>
you should build the dictionary in XAML
this will look as follows
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF_ScratchPad">
<Color x:Key="MyGreen">#0ad30c</Color>
</ResourceDictionary>
then as your are correctly doing you merge the controls dictionary
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyColors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
If you really need to create your dictionary in code then you would merge it as follows
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<yourxmlns:MyColors/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
once you have added the dictionary to the control you don'[t need to instantiate a separate instance of the dictionary to access it instead just call TryFindResource as this keeps the override structure intact

XAML: How can I change the source of a specific ResourceDictionary

<Application x:Class="CDesign.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CDesign"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary x:Uid="Accents" x:Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary x:Uid="BaseTheme" x:Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
How can I change the source of a specific ResourceDictionary inside ResourceDictionary.MergedDictionaries based on the ResourceDictionary's x:Name/x:Uid?
Thanks.
I don't think you can do that based on x:Name or x:Uid. ResourceDictionary does not define mappings for those markup properties. For example, UIElement is marked with UidPropertyAttribute("Uid") and so UIElement marked with x:Uid attribute will have that value available as Uid property. Same story with x:Name. But ResourceDictionary does not define such mappings, and so those properties are effectively lost after xaml is parsed and compiled.
Now, what you can do instead? One option that comes to mind is to use your own attached property to assign resource dictionary an identifier. Unfortunately, ResourceDictionary does not inherit from DependencyObject, and so we cannot use attached properties on it.
However, there is one hack with which we can abuse attached property syntax and still reach the goal. Let's define fake attached property like this:
public static class ResourceDictionaryExtensions {
private static readonly Dictionary<ResourceDictionary, string> _mapping = new Dictionary<ResourceDictionary, string>();
public static void SetName(ResourceDictionary element, string value) {
_mapping[element] = value;
}
public static string GetName(ResourceDictionary element) {
if (!_mapping.ContainsKey(element))
return null;
return _mapping[element];
}
}
Note that this definition is different from usual attached property. First, there is no attached property at all. Second, two methods GetName and SetName do not accept DependencyObject (like methods associated with attached properties do), but ResourceDictionary. However, because we have GetName and SetName methods - we can use attached property syntax, like this:
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary local:ResourceDictionaryExtensions.Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary local:ResourceDictionaryExtensions.Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Even though target object (ResourceDictionary) is not dependency object, and that property is not attached property at all.
Now it's easy to modify source of target dictionary:
var dict = Application.Current.Resources.MergedDictionaries.First(c => ResourceDictionaryExtensions.GetName(c) == "Accents");
dict.Source = new Uri("path to the new dictionary");

wpf modern-ui How can I choose a theme in code behind?

In codeplex's mui, the app.xaml goes like this
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/modernui.light.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
but how can I choose the FirstFloor.ModernUI;component/Assets/modernui.light.xaml" in replace of FirstFloor.ModernUI;component/Assets/modernui.light.xaml" in code behind every time I run the program?
The ModernUI source code comes with a sample application that shows you how to do exactly what you ask.
The library has an AppearanceManager class. Set the current instance ThemeSource property:
AppearanceManager.Current.ThemeSource = AppearanceManager.LightThemeSource;

Categories

Resources