Search code examples
imagexamlthemesavaloniauidynamicresource

Avalonia 11: How to use Image defined in ResourceDictionary depended on Theme


For my Avalonia App i want to use a different Image whether the App is in light or dark mode. Therefor I have the following Styles.axaml file:

<ResourceDictionary xmlns="https://github.com/avaloniaui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Light">
            <SolidColorBrush x:Key="FontColor">#000000</SolidColorBrush>
            <SolidColorBrush x:Key="Accent">#00adb5</SolidColorBrush>
            <ImageBrush x:Key="SomeImage" Source="/Assets/SomeImage-Light.png"/>
        </ResourceDictionary>
        <ResourceDictionary x:Key="Dark">
            <SolidColorBrush x:Key="FontColor">#ffffff</SolidColorBrush>
            <SolidColorBrush x:Key="Accent">#00adb5</SolidColorBrush>
            <ImageBrush x:Key="SomeImage" Source="/Assets/SomeImage-Dark.png"/>
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
    
</ResourceDictionary>

I use this in my App.axaml as follows:

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="SomeNamespace.App"
             RequestedThemeVariant="Default">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceInclude Source="/Accents/Styles.axaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

    <Application.Styles>
        <FluentTheme>
            <FluentTheme.Palettes>
                <ColorPaletteResources x:Key="Light" RegionColor="#EEEEEE" Accent="#00ADB5"/>
                <ColorPaletteResources x:Key="Dark" RegionColor="#2b2b2b" Accent="#0D7377"/>
            </FluentTheme.Palettes>
        </FluentTheme>
    </Application.Styles>
    
</Application>

With this I can use my defined styles like this: <SomeElement Background="{DynamicResource Accent}"/>.

But doing this for the Image does not work. Doing it as follows I get no error but the Image is also not beeing displayed: <Image Source="{DynamicResource SomeImage}"/>.

What am I doing wrong and how can I display an Image depended on the Light and Dark mode?


Solution

  • You should have noticed an error message like the following (for example in the Output Window in Visual Studio) when you debug the application:

    Error in binding to 'Avalonia.Controls.Image'.'Source': 'Unable to convert object 'Avalonia.Media.ImageBrush' of type 'Avalonia.Media.ImageBrush' to type 'Avalonia.Media.IImage'.

    This is because the Image.Source property expects an instance of a type that implements IImage, e.g. a Bitmap, but your resources are of type ImageBrush.

    Change your ResourceDictionary like this:

    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Light">
            ...
            <Bitmap x:Key="SomeImage">/Assets/SomeImage-Light.jpg</Bitmap>
        </ResourceDictionary>
        <ResourceDictionary x:Key="Dark">
            ...
            <Bitmap x:Key="SomeImage">/Assets/SomeImage-Dark.jpg</Bitmap>
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
    

    Alternatively you could keep the ImageBrush resources, but then you would use them like any other Brush, i.e. for the Background or Fill property, like

    <Rectangle Fill="{DynamicResource SomeImage}"/>