0

Creating button which reacts to a dynamic resource (style for dark and light themes) is done like this:

<Button>
  <Image Source="{DynamicResource IconId_12}" />
</Button>

The difficulty comes about when attempting the same concept for an ItemsControl of buttons with different icons for each button, each which have a key which refers to either a dark or light themed image source:

<ItemsControl ItemsSource="{Binding ButtonVMs}">
  <ItemsControl.Resources>
    <DataTemplate DataType="{x:Type ButtonVM}">
      <Button Command="{Binding ClickCommand}">
        <Image Source="{DynamicResource {Binding IconKey}}" />
      </Button>
    </DataTemplate>
  </ItemsControl.Resources>
</ItemsControl>

Where ButtonVM looks like this:

public class ButtonVM {
  public Command ClickCommand { get; set; }
  public string IconKey { get; set; }
}

How can I accomplish binding the resource key name into the dynamic binding?

I have noted that in code you can use <FrameworkElement>.SetResourceReference(SourceProperty, "IconKey"). (as suggested in this stackoverflow answer). But the problem here is that the VM is not a FrameworkElement.

Riley
  • 37
  • 1
  • 6

1 Answers1

0

Using a multi-value converter, I was able to access the FrameworkElement (Image) and utilize .SetResourceReferece() to achieve the effect I needed.

  public class ImageSourceKeyToDynamicResourceConverter : IMultiValueConverter
  {
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
      var image = (Image)values[0];
      var key = (string)values[1];
      image.SetResourceReference(Image.SourceProperty, key);
      return frameworkElement.GetValue(Image.SourceProperty);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
      throw new NotImplementedException();
    }
  }

The xaml sideof things:

<Image>
  <Image.Source>
    <MultiBinding Converter="{StaticResource KeyToDynamicResourceConverter}">
      <Binding RelativeSource="{RelativeSource Self}" />
      <Binding Path="IconKey" Mode="OneWay" />
    </MultiBinding>
  </Image.Source>
</Image>
Riley
  • 37
  • 1
  • 6