Binding a datacontext string property to a StaticResource key
Asked Answered
H

2

11

I have an List values with a ResourceKey and a Caption, these values are both strings. The Resource is the name of an actual resource defined in a resource dictionary. Each of these ResourceKey Icons are Canvas's.

<Data ResourceKey="IconCalendar" Caption="Calendar"/>
<Data ResourceKey="IconEmail" Caption="Email"/>

I then have a list view which has a datatemplate with a button and a text caption below the button. What I want to do is display Resource static resource as the content for the button.

<ListView.ItemTemplate>
    <DataTemplate>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <Button Content="{Binding ResourceKey}" Template="{StaticResource  RoundButtonControlTemplate}"/>
            <TextBlock Grid.Row="1" Margin="0,10,0,0" Text="{Binding Caption}" HorizontalAlignment="Center" FontSize="20" FontWeight="Bold" />
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

I think I have tried every permutation with binding staticresource etc.

I am open to alternatives, I know it may be easier to just have an image and set the source property.

Thanks

Haploid answered 29/3, 2009 at 23:31 Comment(0)
H
15

After having a little think I ending up using a ValueConvertor like so:

class StaticResourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var resourceKey = (string)value;

        return Application.Current.Resources[resourceKey];
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new Exception("The method or operation is not implemented.");
    }
}

and the binding on the button becomes

<Button Content="{Binding ResourceKey, Converter={StaticResource resourceConverter}}" />
Haploid answered 29/3, 2009 at 23:58 Comment(2)
Use FindResource instead of index accessor []: return Application.Current.FindResource(value); it will search in all resources, not in just app.xamlPemberton
Don't know why, but I had to use App.Current.Resources as opposed to Application.Current.ResourcesTonina
M
7

Here I've got an improved version of @dvkwong 's answer (along with @Anatoliy Nikolaev 's edit):

class StaticResourceConverter : MarkupExtension, IValueConverter
{
    private Control _target;


    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var resourceKey = (string)value;

        return _target?.FindResource(resourceKey) ?? Application.Current.FindResource(resourceKey);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var rootObjectProvider = serviceProvider.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
        if (rootObjectProvider == null)
            return this;

        _target = rootObjectProvider.RootObject as Control;
        return this;
    }
}

usage:

<Button Content="{Binding ResourceKey, Converter={design:StaticResourceConverter}}" />

The primary change here is:

  1. The converter is now a System.Windows.Markup.MarkupExtension so it can be used directly without being declared as a resource.

  2. The converter is context-aware, so it will not only look up in your App's resources, but also local resources (current window, usercontrol or page etc.).

Mcneal answered 15/4, 2016 at 7:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.