Why is setting a TemplateBinding on an ImageSource throwing a KeyNotFoundException?

110 views Asked by At

I have the following ListBox subclass...

public class ImageAnnotationEditor : ListBox {

    static ImageAnnotationEditor() {

        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(ImageAnnotationEditor),
            new FrameworkPropertyMetadata(typeof(ImageAnnotationEditor)));
    }

    #region ImageSource Property

        public static readonly DependencyProperty ImageSourceProperty = Image.SourceProperty.AddOwner(
            typeof(ImageAnnotationEditor));

        public ImageSource? ImageSource {
            get => (ImageSource)GetValue(ImageSourceProperty);
            set => SetValue(ImageSourceProperty, value);
        }

    #endregion ImageSource Property
}

With the following template...

<ControlTemplate TargetType="{x:Type c:ImageAnnotationEditor}">

    <Border
        Background="{TemplateBinding Background}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}">

        <Viewbox Stretch="Uniform"
            HorizontalAlignment="Center"
            VerticalAlignment="Center">

            <c:LayerPanel>
                <Image Source="{TemplateBinding ImageSource}" />   <-- This line causes the problem
                <StackPanel IsItemsHost="True" />
            </c:LayerPanel>

        </Viewbox>

    </Border>

</ControlTemplate>

That when I run the app, it throws the following...

System.Collections.Generic.KeyNotFoundException: 'The given key was not present in the dictionary.'

If I remove Source="{TemplateBinding ImageSource}" from the ControlTemplate, it runs without crashing, but of course doesn't display the image.

1

There are 1 answers

1
Clemens On BEST ANSWER

No idea why exactly a KeyNotFoundException is thrown, but the TemplateBinding would work if you register a new DependencyProperty, instead of adding an owner type to Image.SourceProperty. This would also avoid the dependency on the Image class.

public static readonly DependencyProperty ImageSourceProperty =
   DependencyProperty.Register(
       nameof(ImageSource), typeof(ImageSource), typeof(ImageAnnotationEditor));

Otherwise, use the usual workaround, i.e. replace the TemplateBinding by a regular Binding with RelativeSource TemplatedParent:

<Image Source="{Binding ImageSource,
                RelativeSource={RelativeSource TemplatedParent}}"/>