Resource Dictionary for DLL in C# WPF - c#

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

Related

WPF Resources in class library in .NET 5

Before, in .NET Framework, when I created a WPF class library, I had my App.xaml (set as Application definition) referencing my resource dictionaries like that:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml" />
<ResourceDictionary Source="ResourceDictionary2.xaml" />
<ResourceDictionary Source="ResourceDictionary3.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
However, now, with .NET 5, I get this compilation error:
Library project file cannot specify ApplicationDefinition element.
So that message means I can't have an App.xaml file in a class library anymore. But now, I don't know how to define my resources globally in a class library. Isn't there any way to do this without referencing the dictionaries in each and every XAML file in the project?
Edit: It's not about the Source syntax. The path is correct and everything compiles perfectly if I set the project to Windows Application instead of Class Library.
refering to that github issue : https://github.com/dotnet/wpf/issues/2812#issuecomment-607537794
In an SDK style WindowsDesktop project,
*.xaml are all treated as Page items by default, unless they are named App.xaml (C#) or Application.xaml (VB).
App.xaml/Application.xaml is treated as ApplicationDefinition by default.
<!--
Disables automatic globbing of App.xaml/Application.xaml into
ApplicationDefinition item
App.xaml/Application.xaml would now get treated as any other *.xaml file
(typically, a Page)
-->
<PropertyGroup>
<EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
</PropertyGroup>
Worth a try.
For me works the following: If you have library-project with resources (i.e. namespace "Project.Resources") and have presentation-project (i.e. namespace "Project.Presentation"):
<Application x:Class="Project.Presentation.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Project.Resources;Dictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Don't forget to add reference to "Project.Resources" in "Project.Presentation".

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

Using (merged) Resource Dictionary in C# Class Library Project

How can I use a (merged) WPF Resource Dictionary in a C# class library project?
Here is what I did:
In my C# class library project I have a file Dictionary1.xaml like that:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Style x:Key="PluginFrameBorderStyle">
...
</Style>
</ResourceDictionary>
Then, I have a UserControl file UserControl1.xaml where I try to use the Dictionary like that:
<UserControl x:Class="EditorPackageA.BackboneMemberB1Editor.BackboneMemberB1Editor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:EditorPackageA.EditorBase"
xmlns:prism="http://www.codeplex.com/prism" d:DesignWidth="690.4" d:DesignHeight="460.12">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
...
</UserControl>
The project compiles but at runtime I get the error:
with the exception detail:
The same approach works when applied within a WPF project rather than a Class Library project.
What might be the solution here?
Important Addendum:
During design-time I see the effect of the used style that is embedded via the ResourceDictionary, hence the URI of the style and the dictionary must be correct!?
Try to use so called pack URI. I think that you have to explicitly specify where the resource dictionary is located.
<ResourceDictionary Source="pack://application:,,,/TheNameOfClassLibrary;component/Dictionary1.xaml"/>
In the case of a WPF project your approach works because WPF engine by default looks for resource in the assembly being executed (in exe).
You should refer/link the ResourceDictionary xml file to the Source attribute with assembly and component name.
Use relative path as follows:
<ResourceDictionary Source="../Dictionary1.xaml" />
If it is not working, then try PACK URL
<ResourceDictionary Source="pack://application:,,,/Your.Base.AssemblyName;component/DictionaryFolder/Dictionary1.xaml" />
Hope it helps you
You probably need to merge your library's resource dictionary in your application resources. You need to edit your App.xaml file and add something like:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourAssembly;component/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

How to place XAML-only resources in a DLL (Reference) file to be used by WPF applications?

My WPF applications are reaching the level of complexity at which it becomes desirable to place some of the code and other resources inside a Reference file (*.dll).
I am sure I can figure out how to do this, by following the myriad applications out there.
In this particular case, however, the files are two, XAML:
Can somebody please provide an example on how to expose or publish the XAML resources? Are *.cs files required?
TIA
The XAML file outlined by #HighCore should look like this:
<Application x:Class="Application"
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:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
XAML ResourceDictionaries do not generate classes. I'm not sure why you would expect such thing.
Simply move the needed ResourceDictionary definitions to a separate assembly then use the Pack URI Syntax to merge these resources to your application's Resources in app.xaml:
<Application ....>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Find resource from Generic.xaml programmatically

I am trying to implement Style Binding from this article in WPF & Silverlight.
I have a resource dictionary, generic.Xaml with this code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AComponent;component/Themes/MyCustomStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
Where MyCustomStyles.xaml begins like this
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<t:ThemeColorProvider x:Key="ThemeProvider"/>
I need to get the instance of ThemeProvider to update colors/brushes that I am binding to in Generic.xaml. Is it possible to get the instance of the resource keyed "ThemeProvider" so I can update it?
Extra credit if you know a cross platform WPF & Silverlight implementation!
Note: I need to get this outside of the assembly that declares Generic.xaml
If your resource is defined in generic.xaml or any resource that is defined in MergedDictionaries in App.xaml then you need to use Application.Current.Resources, e.g.:
BackgroundColor =
(Color)Application.Current.Resources["ApplicationBarBackgroundColor"]
This may help:
ThemeColorProvider value= (ThemeColorProvider)FindResource("ThemeProvider");
// update value

Categories

Resources