Reputation: 543
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
Upvotes: 11
Views: 13175
Reputation: 1779
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:
The converter is now a System.Windows.Markup.MarkupExtension
so it can be used directly without being declared as a resource.
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.).
Upvotes: 7
Reputation: 543
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}}" />
Upvotes: 15