wpfxamlbindingworkflow-foundation-4

Set BitmapImage dynamically via Binding using a converter in XAML


I have the following xaml (Note this is used in a Microsoft Workflow Foundation activity and is contained within a <sap:ActivityDesigner.Icon>. Hopefully, it won't matter but I thought I'd mention it.)

<DrawingBrush>
    <DrawingBrush.Drawing>
        <ImageDrawing>
            <ImageDrawing.Rect>
                <Rect Location="0,0" Size="16,16" ></Rect>
            </ImageDrawing.Rect>
            <ImageDrawing.ImageSource>
                <BitmapImage UriSource="MyImage.png"/>
            </ImageDrawing.ImageSource>
        </ImageDrawing>
    </DrawingBrush.Drawing>
</DrawingBrush>

I need to change the UriSource at run-time so I thought I'd use a converter as such:

<DrawingBrush>
    <DrawingBrush.Drawing>
        <ImageDrawing>
            <ImageDrawing.Rect>
                <Rect Location="0,0" Size="16,16" ></Rect>
            </ImageDrawing.Rect>
            <ImageDrawing.ImageSource>
                <BitmapImage UriSource="{Binding Path=MyObject, Converter={StaticResource NameToImageConverter}}"/>
            </ImageDrawing.ImageSource>
        </ImageDrawing>
    </DrawingBrush.Drawing>
</DrawingBrush>

but if try to bind it to my object and use a converter, I'm getting the following error:

The provided DependencyObject is not a context for this Freezable

Note that it doesn't hit my converter.

I found The provided DependencyObject is not a context for this Freezable WPF c# which I thought would help but to no avail.

When setting a name to the BitmapImage object

<BitmapImage Name="MyBitmapImage"/>

I thought I'd be able to set this via code but I still get the same error.

I don't know what I've done since originally looking at this but originally I got an error saying something along the lines that I should use a beginInit and endInit. Sorry don't have the exact error since I can't replicate it.

Any ideas on how this can be achieved?

Thanks.


Solution

  • A BitmapImage implements the ISupportInitialize interface and can only be initialized once, and not changed later. If your MyObject is supposed to change its value during runtime and notify the UI, that won't work.

    You can change the Binding to

    <ImageDrawing
        ImageSource="{Path=MyObject, Converter={StaticResource NameToImageConverter}}"
        Rect="0,0,16,16" />
    

    and make the Binding Converter return a BitmapImage instead of an Uri:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ...
        string uri = ...;
        return new BitmapImage(new Uri(uri));
    }