Using BitmapIcon Markup Extension from CommunityToolkit with ThemeResource

34 views Asked by At

I have this XAML code in WinUI 3:

<ctc:SettingsCard Header="Directory">
    <ctc:SettingsCard.HeaderIcon>
        <BitmapIcon ShowAsMonochrome="False" UriSource="{ThemeResource DirectoryIcon}"/>
    </ctc:SettingsCard.HeaderIcon>
</ctc:SettingsCard>

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
         <x:String x:Key="DirectoryIcon">/Assets/DirectoryIconLight.png</x:String>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
         <x:String x:Key="DirectoryIcon">/Assets/DirectoryIconDark.png</x:String>
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Above code works fine.

There is a BitmapIconExtension in CommunityToolkit.WinUI, an example of which looks like this:

<MenuFlyout xmlns:ui="using:CommunityToolkit.WinUI">

    <!--Before-->
    <MenuFlyoutItem Text="Click me!">
        <MenuFlyoutItem.Icon>
            <BitmapIcon Source="/Assets/myicon.png"/>
        </MenuFlyoutItem.Icon>
    </MenuFlyoutItem>

    <!--After-->
    <MenuFlyoutItem
        Text="No, click me!"
        Icon="{ui:BitmapIcon Source=/Assets/myicon.png}" />
</MenuFlyout>

So, I should be able to do this:

<ctc:SettingsCard Header="Directory" HeaderIcon="{ui:BitmapIcon Source={ThemeResource DirectoryIcon},ShowAsMonochrome=False}"/>

But this code doesn't work. I'm getting this error:

Microsoft.UI.Xaml.Markup.XamlParseException: 'The text associated with this error code could not be found.

Failed to assign to property 'CommunityToolkit.WinUI.BitmapIconExtension.Source'. [Line: 142 Position: 39]'

Is it even possible to use this markup extension with Static/Theme resources from ResourceDictionary?

1

There are 1 answers

0
Andrew KeepCoding On BEST ANSWER

I tried to make it work what you are trying to achieve but it seems to be impossible.

Now let me suggest an alternative with a ValueConverter:

public class StringToBitmapIconConverter : IValueConverter
{
    public object? Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is not string path)
        {
            return null;
        }

        if (path.StartsWith("ms-appx:") is false)
        {
            path = $"ms-appx://{path}";
        }

        return new BitmapIcon
        {
            UriSource = new Uri(path),
        };

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
}

then use it like this:

<ctc:SettingsCard
    Header="Directory"
    HeaderIcon="{Binding Source={ThemeResource DirectoryIcon}, Converter={StaticResource StringToBitmapIconConverter}}" />