3
votes

I have an app in which I have defined multiple ThemeResources to set the correct Source for multiple images that I would like to use. I have about a dozen Images for which I can let the app automatically set the Light or Dark theme as required.

<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
        <Style x:Key="ShowImage" TargetType="Image">
            <Setter Property="Source" Value="Assets/image-light.png"/>                            
        </Style>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
        <Style x:Key="ShowImage" TargetType="Image">
            <Setter Property="Source" value="Assets/image-dark.png"/>
        </Style>
    </ResourceDictionary>                
</ResourceDictionary.ThemeDictionaries>

Now if I want set a specific Image inline in XAML I use the following code.

<Grid>        
    <Image HorizontalAlignment="Center" 
       VerticalAlignment="Center" 
       Stretch="None" 
       Style="{ThemeResource ShowImage}">
    </Image>
</Grid>

This works perfectly for all my images and follows the correct theme always.

I'am now trying to change this code. The image that i must show is based on some logic and calculations which i perform in an MVVM ViewModel.

In my ViewModel I have a property of type string 'ImageToShow' that contains the name of the ThemeResource for the Image that must be shown.

I would like to use the property in the ViewModel to perform the ThemeResource assignment to the Image control. so for example the following .. in this case the property ImageToshow would contain the string value ShowImage.

<Grid>        
    <Image HorizontalAlignment="Center" 
       VerticalAlignment="Center" 
       Stretch="None" 
       Style="{ThemeResource ImageToShow}">
    </Image>
</Grid>

This however gives me a XamlParseException.

Is it possible to set the ThemeResource through binding from MVVM? Or should I use some sort of converter to make sure that the value of the string is used to select the ThemeResource.

1
<Image Source="{Binding ImageToShow}"/> - Barnstokkr

1 Answers

1
votes

I believe that you should be able to access the relevant resource for the currently selected Theme using the Application.Current.Resources object... eg.:

Image image = (Image)Application.Current.Resources["ShowImage"];

Therefore, you should be able to return that value from the setter of your view model property like this:

public Image ImageToShow
{
    get { return (Image)Application.Current.Resources["ShowImage"]; }
}

The only problem with this is that you will need to manually notify the INotifyPropertyChanged interface when the property value has changed so that the UI will be notified of the change:

NotifyPropertyChanged("ImageToShow");

You can find an example of how to do that in the User Interface : Detecting Changes in the Theme Template page on the MSCerts website.

Please refer to the How to apply theme resources for Windows Phone page on MSDN for further information.