How to load style using xamlreader - wpf

How can i load style from below xaml using XamlReader.Load()
<Window
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"
>
<ResourceDictionary>
<Style x:Key="LastRowHighlighted"
BasedOn="{StaticResource {dxgt:GridRowThemeKey ResourceKey=RowStyle}}"
TargetType="{x:Type dxg:GridRowContent}">
</Style>
</ResourceDictionary>

Try something like this:
public void LoadStyle(string fileName)
{
if (File.Exists(fileName))
{
try
{
using (FileStream fileStream = new FileStream(fileName, FileMode.Open,
FileAccess.Read, FileShare.Read))
{
ResourceDictionary resourceDictionary = (ResourceDictionary)XamlReader.
Load(fileStream);
Resources.MergedDictionaries.Clear(); // optional
Resources.MergedDictionaries.Add(resourceDictionary);
}
}
catch { }
}
}

Related

MetroDialog with custom background color

I want to display a MetroDialog with a custom background color, for error messages.
I tried using the property CustomResourceDictionary without luck:
Function to display message:
public static async Task<MessageDialogResult> DialogOK(string title, string message)
{
MetroDialogSettings settings = new MetroDialogSettings();
settings.CustomResourceDictionary = new ResourceDictionary { Source = new Uri("pack://application:,,,/MyApp;component/Resources/ErrorDialogRD.xaml") };
var result = await mainWindow.ShowMessageAsync(title, message, MessageDialogStyle.Affirmative, settings );
return result;
}
Resource dictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro">
<Style TargetType="{x:Type Dialogs:BaseMetroDialog}">
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
What am I missing? :)

WPF MahApps.Metro Embedded Dll Resource not working

my problem is that the embedded dlls of MahApps.Metro and MahApps.Metro.IconPacks are not working fine.
Used the Visual Studio debugger to check if they are getting loaded and it worked fine. If it could not load them the program would throw a xaml exception.
But for some reason the ResourceDictionaries which are merged are not working in runtime.
Should look like this
But looks like this
(As you can see the text color is different and it is missing the icon on the right side => does not load the styles.)
It looks like the first picture if both Dll's are provided in the directory of the program.
My App.xaml
<Application x:Class="Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:Launcher.Class.Converter"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<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" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatSlider.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro.IconPacks;component/Themes/IconPacks.xaml" />
<ResourceDictionary Source="Controls\ColorBrushes.xaml"/>
<ResourceDictionary Source="Controls\CustomMetroWindow.xaml"/>
<ResourceDictionary Source="Controls\CustomListView.xaml"/>
<ResourceDictionary Source="Controls\NewsStyle.xaml"/>
<ResourceDictionary Source="Controls\TextImageBox.xaml"/>
<ResourceDictionary Source="Controls\GlowMetroButton.xaml"/>
<ResourceDictionary Source="Controls\ToggleSwitchWin10.xaml"/>
<ResourceDictionary Source="Simple Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<converter:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<converter:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<converter:BooleanToVisibilityCollapsedConverter x:Key="BoolToVisibilityCollapsedConverter" />
<converter:MultiObjectToBooleanConverter x:Key="MultiObjectToBooleanConverter" />
<converter:DownloadProgressToVisibilityConverter x:Key="DownloadProgressToVisibilityConverter" />
<converter:MultiObjectToStatusBarColorConverter x:Key="MultiObjectToStatusBarColorConverter" />
<converter:MultiBooleanConverter x:Key="MultiBooleanConverter" />
<converter:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibilityConverter" />
<converter:OpacityToBooleanConverter x:Key="OpacityToBooleanConverter" />
</ResourceDictionary>
</Application.Resources>
My Program.cs
[STAThread]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var resourceName = Assembly.GetExecutingAssembly().GetName().Name + ".Dll." + new AssemblyName(args.Name).Name + ".dll";
if (!resourceName.Contains("resources"))
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (stream != null)
{
var assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
}
else
{
Assembly requestedAssembly = args.RequestingAssembly;
AssemblyName requestedAssemblyName = new AssemblyName(args.Name);
while (true)
{
// requesting name in format: %assemblyname%.resources
// rewrite to: %assemblyName%.%assemblyName%.%culture%.resources.dll
//
var baseName = requestedAssemblyName.Name.Substring(0, requestedAssemblyName.Name.Length - ".resources".Length);
var name = string.Format("{0}.Dll.Lang.{1}.{2}.resources.dll", baseName, requestedAssemblyName.CultureInfo.Name, Assembly.GetExecutingAssembly().GetName().Name);
// by default for resources the requestingAssembly will be null
Assembly asm = null;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
// resources have the same name as their belonging assembly, so find by name
var parentName = requestedAssemblyName.Name.Substring(0, requestedAssemblyName.Name.Length - ".resources".Length);
// I'd love to use linq here, but Cecil starts fucking up when I do (null reference exception on assembly.Write)
// without a Linq query it works fine, though
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var assembly in assemblies)
{
if (assembly.GetName().Name == parentName)
{
asm = assembly;
}
}
if (asm == null)
{
// cannot find assembly from which to load
return null;
}
using (var stream = asm.GetManifestResourceStream(name))
{
if (stream != null)
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Assembly.Load(bytes);
}
}
// did not find the specific resource yet
// attempt to use the parent culture, this follows the .Net resource fallback system
// e.g. if sub resource de-DE is not found, then .Parent will be "de", if that is not found parent will probably be default resource
var fallback = requestedAssemblyName.CultureInfo.Parent.Name;
if (string.IsNullOrEmpty(fallback))
{
// is empty if no longer a parent
// return null so .Net can load the default resource
return null;
}
var alteredAssemblyName = requestedAssemblyName.FullName;
alteredAssemblyName = alteredAssemblyName.Replace(string.Format("Culture={0}", requestedAssemblyName.CultureInfo.Name), string.Format("Culture={0}", fallback));
requestedAssemblyName = new AssemblyName(alteredAssemblyName);
}
}
return null;
};
App.Main();
}
The control
<TextBox x:Name="Username"
Controls:TextBoxHelper.Watermark="{lex:Loc Key=LoginWindow.YourUsername}" Margin="0,20,0,9"
Text="{Binding Config.AuthUsername}"
IsEnabled="{Binding LoggingIn, Converter={StaticResource InverseBooleanConverter}}" TextAlignment="Justify"
>
<TextBox.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource MetroTextImageBox}">
<Setter Property="Controls:TextBoxHelper.ButtonTemplate">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Grid Background="{TemplateBinding Background}">
<Rectangle>
<Rectangle.Fill>
<VisualBrush>
<VisualBrush.Visual>
<iconPacks:PackIconModern Kind="User" Foreground="{StaticResource MainIconBrush}" />
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>
This code works for me: (add all libraries as Embedded Resource and set startup object to this class)
public class Program
{
private static Assembly ExecutingAssembly = Assembly.GetExecutingAssembly();
private static string[] EmbeddedLibraries =
ExecutingAssembly.GetManifestResourceNames().Where(x => x.EndsWith(".dll")).ToArray();
[STAThreadAttribute]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
App.Main();
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// Get assembly name
var assemblyName = new AssemblyName(args.Name).Name + ".dll";
// Get resource name
var resourceName = EmbeddedLibraries.FirstOrDefault(x => x.EndsWith(assemblyName));
if (resourceName == null)
{
return null;
}
// Load assembly from resource
using (var stream = ExecutingAssembly.GetManifestResourceStream(resourceName))
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Assembly.Load(bytes);
}
}
}
The project file portion was cut off previous answer.
Add this to project file
<!--Then add this is project file.-->
<Target Name="EmbedReferencedAssemblies" AfterTargets="ResolveAssemblyReferences">
<ItemGroup>
<!-- get list of assemblies marked as CopyToLocal -->
<AssembliesToEmbed Include="#(ReferenceCopyLocalPaths)" Condition="'%(Extension)' == '.dll'" />
<!-- add these assemblies to the list of embedded resources -->
<EmbeddedResource Include="#(AssembliesToEmbed)">
<LogicalName>%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
<Message Importance="high" Text="Embedding: #(AssembliesToEmbed->'%(DestinationSubDirectory)%(Filename)%(Extension)', ', ')" />
</Target>
<!-- no need to copy the assemblies locally anymore -->
<Target Name="_CopyFilesMarkedCopyLocal" />
I had the same issue you described and came across fix that resolves the issue.
public partial class App : Application {
public App() {
AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
}
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) {
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyName = new AssemblyName(args.Name);
var path = assemblyName.Name + ".dll";
if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) {
path = String.Format(#"{0}\{1}", assemblyName.CultureInfo, path);
}
using (var stream = executingAssembly.GetManifestResourceStream(path)) {
if (stream == null)
return null;
var assemblyRawBytes = new byte[stream.Length];
stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
return Assembly.Load(assemblyRawBytes);
}
}
}
%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)
'%(DestinationSubDirectory)%(Filename)%(Extension)',
', ')" />

ResourceDictionary Locator

Is there a way to create a ResourceDictionary Locator.
Right now I have in xaml:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Resources/StringResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Where the code behind sets the list of dictionaries based on currentculture
I'd like to have
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<Locator "StringResources"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Or something like that such that I don't have to modify each v.xaml.cs files
You could create your own ResourceDictionary:
public class ResourceDictionaryLocator : ResourceDictionary
{
public ResourceDictionaryLocator()
{
switch (CurrentLocalization)
{
case "English":
base.Source = new Uri("pack://application:,,,/Languages/English.xaml");
break;
case "French":
base.Source = new Uri("pack://application:,,,/Languages/French.xaml");
break;
}
}
}
Then consume it like this:
<Application x:Class="TestingWPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestingWPF"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:ResourceDictionaryLocator />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
This is generally not done, however. You can load different resource dictionaries at runtime. Something like the following:
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dictionary);
You can create a MarkupExtension that will return the requested ResourceDictionary:
public class ResourceDictionaryLocator : MarkupExtension
{
public string DictionaryName { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
// Logic to return the wanted ResourceDictionary
if (DictionaryName == "...")
{
}
return null;
}
}
Then use it in xaml:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:ResourceDictionaryLocator DictionaryName="StringResources" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
I really don't know if this is posible, but do you want to make that your application be 'Localizable'? Baybe this article could be helpful to you: http://www.codeproject.com/KB/WPF/WPF_Resx_Localization/.

Silverlight Multi-state toggle button

Is there such a thing as a multi-state togglebutton in silverlight? I've tried retemplating radio buttons in a group, but I'd like to make a storyboard that works across the toggle states and because radio buttons are separate objects I'm stuck(I'm trying to make it look like the iphone toggle button, except multi-state)
The standard Silverlight CheckBox as an IsThreeState property. The default visual for the third state is "-", so you might have to customise the visuals.
A CheckBox is a specialisation of a ToggleButton.
You probably know of OOTB checkbox control:
http://samples.msdn.microsoft.com/Silverlight/SampleBrowser/#/?sref=System.Windows.Controls.CheckBoxEx
That was probably useful, but for one of my projects, it had to be similar functionality but using an input box instead so I used custom UserControl approach. I'd highly recommend it.
In the constructor of usercontrol, after InitializeComponent(); you can specify the values that affect the UI. Time permitting I'll annotate some xaml+cs.
Here's some code:
XAML:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Style x:Key="TernaryTB" TargetType="TextBox">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Width" Value="64"/>
<Setter Property="Height" Value="39"/>
<Setter Property="FontWeight" Value="ExtraBold"/>
<Setter Property="FontFamily" Value="Portable User Interface"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextAlignment" Value="Center" />
</Style>
</Grid.Resources>
<TextBox x:Name="BackgroundTextBox" IsEnabled="True" BorderBrush="White" Foreground="{x:Null}" Visibility="Visible" Style="{StaticResource TernaryTB}"/>
<TextBox x:Name="TernaryTextBox" Style="{StaticResource TernaryTB}" GotFocus="TernaryTextBox_GotFocus"/>
</Grid>
</UserControl>
CS:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
private int current;
public int Current
{
get
{
return current;
}
set
{
current = value;
}
}
public struct DataStructure
{
private string label;
private Color color;
private Color forecolor;
public DataStructure(string label, Color c, Color c2)
{
this.label = label;
this.color = c;
this.forecolor = c2;
}
public string Label
{
get { return label; }
set { label = value; }
}
public Color Color
{
get { return color; }
set { color = value; }
}
public Color Forecolor
{
get { return forecolor; }
set { forecolor = value; }
}
}
IList<DataStructure> DataStructureArray;
public MainPage()
{
InitializeComponent();
current = 0;
int i = 0;
DataStructureArray = new Collection<DataStructure>
(new[] {
new DataStructure ("A", Colors.Red,Colors.Green),
new DataStructure ("B", Colors.Green,Colors.Blue),
new DataStructure ("C", Colors.Blue,Colors.Red)
});
foreach (DataStructure listItem in DataStructureArray)
{
if (i == current)
{
TernaryTextBox.Text = listItem.Label;
TernaryTextBox.Background = new SolidColorBrush(listItem.Color);
break;
}
i++;
}
}
public MainPage(IList<DataStructure> NewDataStructureArray)
{
int i = 0;
DataStructureArray = new Collection<DataStructure>();
foreach (DataStructure ds in NewDataStructureArray)
{
DataStructureArray.Add(new DataStructure(ds.Label, ds.Color, ds.Forecolor));
i++;
}
}
private void TernaryTextBox_GotFocus(object sender, RoutedEventArgs e)
{
int i = 0;
current = (current + 1) % 3;
foreach (DataStructure listItem in DataStructureArray)
{
if (i == current)
{
TernaryTextBox.Text = listItem.Label;
TernaryTextBox.Background = new SolidColorBrush(listItem.Color);
TernaryTextBox.Foreground = new SolidColorBrush(listItem.Forecolor);
BackgroundTextBox.Focus();
break;
}
i++;
}
BackgroundTextBox.Focus();
}
}
}
To test, simply add a brand spanking usercontrol to your project, copy paste my code; to test my code in isolation, open App.xaml.cs and simply replace:
this.RootVisual = new MainPage();
with:
this.RootVisual = new <Whatevernameyouchosefortheusercontrol>();
to see it in action

Change theme at runtime

I have a WPF application with a theme (ShinyRed.xaml) and I want to have a button that when clicked changes the theme to ShinyBlue.xaml
I load in the theme initially in App.xaml:
<Application.Resources>
<ResourceDictionary Source="/Themes/ShinyBlue.xaml"/>
</Application.Resources>
How might I do this?
How you could do it:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/ShinyRed.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<!-- ... -->
public partial class App : Application
{
public ResourceDictionary ThemeDictionary
{
// You could probably get it via its name with some query logic as well.
get { return Resources.MergedDictionaries[0]; }
}
public void ChangeTheme(Uri uri)
{
ThemeDictionary.MergedDictionaries.Clear();
ThemeDictionary.MergedDictionaries.Add(new ResourceDictionary() { Source = uri });
}
//...
}
In your change method:
var app = (App)Application.Current;
app.ChangeTheme(new Uri("New Uri here"));
Here is an article that will walk you through it:
http://svetoslavsavov.blogspot.com/2009/07/switching-wpf-interface-themes-at.html
Basically you need to remove the "old" theme from the resource dictionary and then merge in the new one. The above article shows you how to make this change very simple.
Im using the following command to set the theme at runtime:
Application.Current.Resources.Source = new Uri("/Themes/ShinyRed.xaml", UriKind.RelativeOrAbsolute);
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Font.xaml" />
<ResourceDictionary Source="Themes/Light.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
In your code:
> Application.Current.Resources.MergedDictionaries[1].Source = new Uri("Themes/Dark.xaml", UriKind.RelativeOrAbsolute);
you can check with this to be sure nothing grow
Application.Current.Resources.MergedDictionaries.Count.ToString();
H.B.'s answer did not run for me, I had to do this (works, tested):
Uri dictUri = new Uri(#"/Resources/Themes/MyTheme.xaml", UriKind.Relative);
ResourceDictionary resourceDict = Application.LoadComponent(dictUri) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDict);
To pretty it up:
// Place in App.xaml.cs
public void ChangeTheme(Uri uri)
{
ResourceDictionary resourceDict = Application.LoadComponent(uri) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDict);
}
// Example Usage (anywhere in app)
private void ThemeRed_Click(object sender, RoutedEventArgs e)
{
var app = App.Current as App;
app.ChangeTheme(new Uri(#"/Resources/Themes/RedTheme.xaml", UriKind.Relative));
}

Resources