0

Say I have the WPF Window defined in XAML:

<Window x:Class="OINA.Papyrus.ReportGeneratorPoCNetv48.MainWindow"
        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"
        xmlns:local="clr-namespace:OINA.Papyrus.ReportGeneratorPoCNetv48"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="800">
    <StackPanel Margin="20" Loaded="OnLoaded">
        <StackPanel.Resources>
            <system:String x:Key="Greeting">Hello, World!</system:String>
            <system:String x:Key="Farewell">Goodbye, World!</system:String>
        </StackPanel.Resources>
        <TextBlock x:Name="myTextBlock" Text="{StaticResource Greeting}" />
    </StackPanel>
</Window>

The TextBlock element has a Text property with the value of "Hello, World!", so within the code-behind we can simply do myTextBlock.Text. But instead of getting the value of the Text property, is there a way to determine the key of the resource that was used to provide the value of the Text property, which in the example of above would be "Greeting"?

Dan Stevens
  • 6,392
  • 10
  • 49
  • 68
  • No, you can't. The key for a style will not be available for any style applied using static resource. – Andy Mar 21 '23 at 21:43
  • What about a DynamicResource? – Dan Stevens Mar 22 '23 at 09:13
  • 1
    https://stackoverflow.com/questions/1660608/given-a-styled-wpf-dependencyobject-how-can-i-get-the-style-key-in-code – Andy Mar 22 '23 at 14:12
  • So long as the style is directly on the control. – Andy Mar 22 '23 at 14:14
  • I guess maybe you want to do localisation or branding. If so, merge a resource dictionary with same key but different value for different company or language. – Andy Mar 22 '23 at 14:26

2 Answers2

1

You would need a place to store information about a key. An attached property fits well.

class AP : DependencyObject
{
    public static string GetResourceKey(DependencyObject obj)
    {
        return (string)obj.GetValue(ResourceKeyProperty);
    }
    public static void SetResourceKey(DependencyObject obj,
       string value)
    {
        obj.SetValue(ResourceKeyProperty, value);
    }

    public static readonly DependencyProperty ResourceKeyProperty =
          DependencyProperty.RegisterAttached("ResourceKey", typeof(string), typeof(AP));

}

Then you need a way to make a resource retrieval feasible as well as storing key value. To do so, create a custom markup extension. Within, you call a regular static resource as well as you assign key's value to the attached property.

class StaticResourceWithkeyMarkup : MarkupExtension
{
    public string Key { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider)
    { 
        var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        var uiElement = target.TargetObject as DependencyObject;
        AP.SetResourceKey(uiElement, Key);
        var staticResource = new StaticResourceExtension(Key); 
        return staticResource.ProvideValue(serviceProvider);
    }
}

The view looks as follows

<StackPanel Margin="20">
    <StackPanel.Resources>
        <system:String x:Key="Greeting">Hello, World!</system:String>
        <system:String x:Key="Farewell">Goodbye, World!</system:String>
    </StackPanel.Resources>
    <TextBlock x:Name="myTextBlock" Text="{local:StaticResourceWithkeyMarkup Key=Farewell}" />
    <Button Content="Click" Click="Button_Click"/>
</StackPanel>

You retrieve a key by checking textBlock attached property

 private void Button_Click(object sender, RoutedEventArgs e)
 {
    var key = AP.GetResourceKey(myTextBlock);
 }
Maximus
  • 3,458
  • 3
  • 16
  • 27
0

Is there a way to determine the key of the resource that was used to provide the value of the Text property?

No. The values has already been looked up and the "connection" to the Greeting resource is not stored somewhere.

What about a DynamicResource?

Then you can try this:

var converter = new ResourceReferenceExpressionConverter();
var value = myTextBlock.ReadLocalValue(TextBlock.TextProperty);
var dynamicResource = new ResourceReferenceExpressionConverter()
    .ConvertTo(value, typeof(MarkupExtension)) as DynamicResourceExtension;
string key = dynamicResource.ResourceKey as string;
mm8
  • 163,881
  • 10
  • 57
  • 88