93

I have a custom collection defined in my window resources as follows (in a Sketchflow app so the window is actually a UserControl):

<UserControl.Resources>
    <ds:MyCollection x:Key="myKey" x:Name="myName" />
</UserControl.Resources>

I want to be able to refer to this collection in the codebehind, which I expected would be by the x:Name, but I can't seem to access it.

I can get a reference to it using

myRef = (MyCollection) this.FindName("myKey");

but this seems hackish. Is this bad practice, and what would be better? Thanks :)

8 Answers 8

106

You should use System.Windows.Controls.UserControl's FindResource() or TryFindResource() methods.

Also, a good practice is to create a string constant which maps the name of your key in the resource dictionary (so that you can change it at only one place).

Sign up to request clarification or add additional context in comments.

4 Comments

You can use: Application.Current.FindResource(errorColorResourceName) as MyCollection or this.FindResource("RainbowBrush") as MyCollection. It depends on the context.
Can you elaborate on "Also, a good practice is to create a string constant which maps the name of your key in the resource dictionary (so that you can change it at only one place)." ? Where would such a string constant go that would change the XAML key as well as the C# code behind?
+1 for > Can you elaborate on "Also, a good practice is to create a string constant which maps the name of your key in the resource dictionary (so that you can change it at only one place)." ? Where would such a string constant go that would change the XAML key as well as the C# code behind?
@MikeChristiansen AdonisUI is a good exemple of that, if you look in src/AdonisUI/Brushes.cs you have a bunch of keys that are used in the templates, for example in Buttons.cs where you have a {DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}.
31

You may also use this.Resources["mykey"]. I guess that is not much better than your own suggestion.

3 Comments

This is for Windows 8 Store Apps.
@cederlof, you can use this with WPF too.
This will not work if the resource is in another file, for instance a theme color. FindResource is the way to go.
24

Not exactly direct answer, but strongly related:

In case the resources are in a different file - for example ResourceDictionary.xaml

You can simply add x:Class to it:

<ResourceDictionary x:Class="Namespace.NewClassName"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <ds:MyCollection x:Key="myKey" x:Name="myName" />
</ResourceDictionary>

And then use it in code behind:

var res = new Namespace.NewClassName();
var col = res["myKey"];

3 Comments

+1, but to be able to find resources using it's key I had to call res.InitializeComponent() before attempting to access the key otherwise the object would show no keys and the call to res["myKey"] would return null.
Wow that's awesome... I never knew you could do that and it just solved a problem for me quick and easy! I did need to call InitializeComponent() like @StephenRoss said but other than that works like a charm.
A perfect solution to use from Converters
11

If you want to access a resource from some other class (i.g. not a xaml codebehind), you can use

Application.Current.Resources["resourceName"];

from System.Windows namespace.

1 Comment

This is useful if you need to access the resource from a static constructor or method, and therefore don't have the ability to call FindResource or TryFindResource.
9

You can use a resource key like this:

<UserControl.Resources>
    <SolidColorBrush x:Key="{x:Static local:Foo.MyKey}">Blue</SolidColorBrush>
</UserControl.Resources>
<Grid Background="{StaticResource {x:Static local:Foo.MyKey}}" />

public partial class Foo : UserControl
{
    public Foo()
    {
        InitializeComponent();
        var brush = (SolidColorBrush)FindResource(MyKey);
    }

    public static ResourceKey MyKey { get; } = CreateResourceKey();

    private static ComponentResourceKey CreateResourceKey([CallerMemberName] string caller = null)
    {
        return new ComponentResourceKey(typeof(Foo), caller); ;
    }
}

1 Comment

Note that this depends on the type of key. E.g. a key in a DataTemplate is of type DataTemplateKey.
1

I got the resources on C# (Desktop WPF W/ .NET Framework 4.8) using the code below

{DefaultNamespace}.Properties.Resources.{ResourceName}

Comments

1

A nice clean example from Microsoft documents makes it simple:

private void myButton_Click(object sender, RoutedEventArgs e)
{
  Button button = (Button)sender;
  button.Background = (Brush)this.FindResource("RainbowBrush");
}

1 Comment

This has already been answered.
0

I know this has been answered but with a more complex form. In this case it is a form with several grids and each one has its own styling resources I discovered the most efficient way to handle this involved two steps (mostly due to the fact that I forgot the adage "Scope matters"):

  1. for accessibility give a name to the control holding the resources

  2. Use the FindResource function of the control to set the child control

From the XAML

   <Grid x:Name="grdJIT">
        <Grid.Resources>
            <ResourceDictionary>
                <LinearGradientBrush x:Key="buttonStyleGradient"  EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="White" Offset="0" />
                    <GradientStop Color="#FFACC3F5" Offset="1" />
                </LinearGradientBrush>
                <LinearGradientBrush x:Key="buttonStyleAlert"  EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="Yellow" Offset="0" />
                    <GradientStop Color="#FFDD2375" Offset="1" />
                </LinearGradientBrush>
            </ResourceDictionary>
        </Grid.Resources>

then in the Code behind (to set the background of a button called "btnGetRG")

          LinearGradientBrush _r = (LinearGradientBrush)grdJIT.FindResource("buttonStyleAlert");
                            btnGetRG.Background = _r;

Like I said, the users question is answered previously and this is just a variant of that answer. I thought it worthwhile as my more specific search through Bing brought me here. Therefore, it seemed worth the post.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.