What is the difference between Application.Current.Resources and Resources - c#

I have global ResourceDictionary defined in my App.xaml file.
<Application.Resources>
<ResourceDictionary>
<Style x:Key="yolo" TargetType="Grid" />
</ResourceDictionary>
</Application.Resources>
I've had set breakpoint in random Page and checked difference in debugger:
Application.Current.Resources = 1
Resources = 0
What's the this.Resources?

Application.Current.Resources
Contains the resources that are declared in the App.xaml file, which can be seen the entire application.
this.Resources
Contains the resources that are defined locally for any control, such as Window, UserControl and are only available within this control.
Example with Window:
XAML
<Window ...
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<Window.Resources>
<sys:String x:Key="MyString">TestString</sys:String>
</Window.Resources>
Code-behind
public MainWindow()
{
InitializeComponent();
string test = this.Resources["MyString"] as string;
}

What's the this.Resources?
It's the resource dictionary of the control whose code-behind code we are writing in.
On the other hand Application.Current.Resources is the resource dictionary of the application object itself.
If you are writing code inside App.xaml.cs, then Resources and Application.Current.Resources will refer to the same object.

Related

Accessing a DynamicResource in code-behind [duplicate]

I have a DataTemplate defined in a xaml file that I want to access via C# code.
Can anyone please tell me how can I access it?
I added a new ResourceDictionary file and its name is Dictionary1.xaml.
I have a data template such as:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="mytemplate">
<TextBlock Text="Name:" Background="Blue"/>
</DataTemplate>
</ResourceDictionary>
not I have a ListBox called listBox1 and I want to assign it to it's Itemtemplate property
but I'm not getting how can i do it?
Since Application.Current was null in my case, I've ended up using this:
var myResourceDictionary = new ResourceDictionary();
myResourceDictionary.Source =
new Uri("/DllName;component/Resources/MyResourceDictionary.xaml",
UriKind.RelativeOrAbsolute);
and then getting the specified key I needed by using
myResourceDictionary["KeyName"] as TypeOfItem
(source)
Where exactly are you defining it?
If you define it in the ResourceDictionary of your object, then
Application.Current.Resources[typeof(yourDataTemplateTargetType)]
should work. If you are defining it as a member of something else, like say, an ItemsControl, you need to get a handle to the ItemsControl instance and call the ItemTemplate property.
Edit: Ok, I think we're getting somewhere. So you are defining a ResourceDictionary in its own file. Before you can use it in your UI and access it from your code behind, you need to merge that ResourceDictionary into your application. Are you doing this?
If you are, then the next step is to get this resource. Each FrameworkElement has a method called FindResource. This method is great because it walks up the ResourceDictionary tree and attempts to locate the resource with the key. So, if you want to access this resource from a UserControl, you can do the following in the code behind:
FindResource(typeof(yourDataTemplateTargetType));
If this doesn't work for you, please show us exactly how you are declaring this resource dictionary and how it is getting merged into your application's resources.
If you for example have a template for Button in your resource dictionary in the App.xaml file you can access it using the following code:
Application.Current.Resources[typeof(Button)]
If you have merged resource dictionary using code like below
<Window x:Class="MainWindow">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DefaultStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</Window>
Then, instead of Application.Current.Resources["ResourceKey"] you need to specify Control name (in this case MainWindow) also like below
var style = Application.Current.MainWindow.Resources["ResourceKey"];
// OR
var style = Application.Current.MainWindow.TryFindResource("ResourceKey");
If you're getting the resources within the same project, try this:
yourControl.Style = FindResource("YourResourceKey") as Style;
Otherwise, try this:
ResourceDictionary res = (ResourceDictionary)Application.LoadComponent(new Uri("/ProjectName;component/FolderName/ResourceDictionaryName.xaml", UriKind.Relative));
yourControl.Style = (Style)res["YourResourceKey"];
You can access a resource dictionary you added to your project as follows:
var rd = new ResourceDictionary();
rd.Source = new Uri("ms-appx:///Dictionary1.xaml");
Then you can access a resource stored in the resource dictionary like so:
someObject.Property = rd["mytemplate"];
NOTE:
You will have to modify the URI to the resource dictionary according to the location you created it relative to the project's base directory.
I found the answer here
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-use-a-resourcedictionary-to-manage-localizable-string-resources
create a ressource dictionary "ColorResources.xaml"
add to it:
Blue
edit your app.xml and add:
use the color from your code
var color = (System.Windows.Media.Color)Application.Current.FindResource("ButtonColor1");
and voilĂ 
ps : admin can you fix the code? it does not show up, thanks
Any of the above approaches work getting the resource based on the location, if you are following MVVMm I would recommend doing it this way:
create a Service like ProvideDataTemplateService, (to create a service usual inherit from Behavior )
Use Container of Your choice to inject this service where you would like to have aces to DataTemple.
For the life of me, although I was able to load my resource dictionary via XAML, I wasn't able to load it via "code behind" (in C#).
So I resorted to have a view loading it: (MyView.xaml)
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/My.Proj;component/My/Path/myResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Then access it in my UT by instanciating that view and accessing it:
new MyView().Resources.MergedDictionaries[0]
Hacky, but works.
Just to add another answer here in case you don't have a view or Application.Current is null. I realize this is probably uncommon but in my case I have an addin to a parent application and Application.Current is null; I also want to pass one of my resources to the parent as an ImageSource so I don't have a XAML view created to get resources from directly.
You can also make the dictionary into a code behind creatable object. Just set the x:Class attribute in the XAML and then create a .xaml.cs file in the code behind. Your updated XAML, lets call the code file MyDictionary.xaml, would then look something like this:
<ResourceDictionary 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"
x:Class="Some.Namespace.MyDictionary"
mc:Ignorable="d">
...Resources...
</ResourceDictionary>
And the code behind (MyDictionary.xaml.cs) would look something like this:
using System.Windows;
namespace Some.Namespace
{
public partial class MyDictionary : ResourceDictionary
{
public MyDictionary()
{
InitializeComponent();
}
}
}
Don't forget to call InitializeComponent() as that's what loads the resources. Actually not sorry, see edit below
After you do this you can simply construct an instance of the class anywhere in code and reference the resources by key like this:
var dictionary = new MyDictionary();
var resource = dictionary["whateverKey"] as WhateverResourceType;
Thanks to this post for leading to the idea.
EDIT
Just ran into one potential issue with this. I got a 'Cannot re-initialize ResourceDictionary instance' exception with this setup on some of my controls. On further research this could be related to calling InitializeComponent in the constructor. Instead I removed the constructor from the code behind and added a static method to get an initialized instance as follows:
public static MyDictionary ConstructInitializedInstance()
{
var dictionary = new MyDictionary();
dictionary.InitializeComponent();
return dictionary;
}
You could also just create and initialize in your code behind.

App wide accessible Flyout in UWP

I have a flyout in my app that I use to add additional contacts into the local database. This flyout is declared as a page resource currently, and does exactly what I need it to, however in order to re-use it on a different page I need to copy both the xaml for the flyout and any attatched events to each page that would require using it (there are several places where a contact might need to be added)
Is there a way to globally define a flyout such that I only need to reference it rather than hardcode it each time? I considered using a ContentDialog (as that can be defined as its own module) but I don't think that would be the right fit
If creating completely in code is not an option you can create a ResourceDictionary with a class in background. First the Styles.xaml:
<ResourceDictionary
x:Class="MyClass.Styles"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Flyout x:Key="MyFlyout">
<!-- my flyout code -->
</Flyout>
</ResourceDictionary>
The important thing here is x:Class, where the value needs to be the namespace+name of the related class we're creating now (Styles.cs in that case):
namespace MyClass {
public partial class Styles {
public Styles() {
this.InitializeComponent();
}
// my events from flyout
}
}
Make sure that the class is declared as partial and calls this.InitializeComponent() in the constructor.
Now in your app resources add a reference:
<Application
...
xmlns:myClass="using:MyClass">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<myClass:Styles />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Then you can access the Flyout as a static resource, e.g.:
<Button Flyout="{StaticResource MyFlyout}" />

XamlParseException when attempting to open a WPF Window from Winforms

I have a single Winforms project and multiple WPF projects in one solution. From the Winform application I'd like to open one of the WPF Windows (it's a MetroWindow from Mahapps, if it matters).
After looking at the accepted answer to this stackoverflow question I ended up with this piece of code:
OpenWPFAppButton_Click(object sender, EventArgs e)
{
WPFApp wpfApp = new WPFApp();
ElementHost.EnableModelessKeyboardInterop(wpfApp);
wpfApp.Show();
}
Unfortunately if I click the button a XamlParseException occurs, which points to the first Style="{StaticResource ... }" line in WPFApp.xaml (the Main Xaml File).
Does this mean I cannot open WPF Windows from Winforms that include static resources? Or am I missing something simple here?
EDIT: Here is the content of the App.xaml file:
<Application x:Class="WPFAppProjectName.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
StartupUri="WPFApp.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/ButtonStyles.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/MenuStyles.xaml"/>
<ResourceDictionary Source="pack://application:,,,/Selen.Wpf.SystemStyles;component/TextBoxStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
It is most likely that some common resources are defined in the App.xaml. That file isn't loaded when running through Windows Forms and thus those resources are unavailable. Hence you get this error.
You could include the resource definitions in the Window.xaml files, or an own common style resource file (aka Resource Dictionary) which is included in every Window.

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

wpf image resources and changing image in wpf control at runtime

I would like to know exactly how to dynamically use a Dictionary Resource in the C# code behind - ie.. I would like to load images at runtime from an image resource within a dictionary
I have a program that has 3 images in a WPF Dictionary - these are images set as image resources.
Then in the code behind of my WPF Window I want to load any one of the three images based on user initiated events.
There is no real code I have to show as nothing that I have done works.
Ideas?
First, make sure you've defined your image resources like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ImageSource x:Key="image1">images/image1.jpg</ImageSource>
<ImageSource x:Key="image2">images/image2.jpg</ImageSource>
</ResourceDictionary>
Secondly, I'm assuming that your WPF dictionary is in its own file. Now you have to make sure you've merged your dictionary into your main window's XAML (skip this step if your resource dictionary is defined inside of the window's XAML). In your window's XAML file, make sure you have something like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="myDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
Now, in your code-behind, you can use the FindResource() method to locate your image resource by it's key name (the value of the x:Key attribute on the ImageSource in the resource dictionary) like so:
imageControl.Source = (ImageSource)FindResource("image1");
Hope this helps!
This is an addition to the accepted answer:
When working within a ViewModel from MVVM, make sure to use the FindResource from the view where the resource directory is added.
<Window x:Class="My.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:My.ViewModels"
Title="USA Hockey Player Evaluation tool"
Icon="/USAHockeyPlayerEval;component/View/Images/HET.ico"
SizeToContent="WidthAndHeight"
MinHeight="500px" MinWidth="800px">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Images.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<ViewModels:MainWindowMV/>
</Window.DataContext>
<StackPanel>
<Menu>
<MenuItem Header="File">
<MenuItem Header="Save"></MenuItem>
My view in this case is a window (I know not correct MVVM ;-) )
Image img = new Image();
img.Source = (ImageSource)WindowReference.FindResource("Pluse");
Here the WindowReference is a reference to My.MainWindow.

Categories

Resources