I've created a small user control consisting of a button whose content is an Image. I created an "ImageSource" dependency property on the user control in order to bind to it from the Image inside the button.
However in the XAML where I placed an instance of my user control setting the property throws an error at runtime :
<ctrl:ImageButton ImageSource="/Resources/Images/Icons/x.png" Command="{Binding Reset}" DisabledOpacity="0.1"/>
and at runtime :
'/Resources/Images/Icons/x.png' string is not a valid value for 'ImageSource' property of type 'ImageSource'. 'ImageSource' type does not have a public TypeConverter class.
I then created a converter :
public class StringToBitmapImage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new BitmapImage(new Uri((string) value, UriKind.RelativeOrAbsolute));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
and then decorated my dependency property with it :
[TypeConverter(typeof(StringToBitmapImage))]
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
LambdaHelper.GetMemberName<ImageButton>(ib => ib.ImageSource), typeof (ImageSource), typeof (ImageButton));
[TypeConverter(typeof(StringToBitmapImage))]
public ImageButton ImageSource
{
get { return (ImageButton)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
but still WPF does not convert my string to an ImageSource (BitmapImage) instance...
What to do?
There are several incorrect things here:
First, your CLR property is returning an ImageButton
whereas the dependency property is defined as an ImageSource
.
Second, a type converter is not the same as a binding value converter. Your type converter should derive from TypeConverter
and be applied on the ImageSource
class rather than on the property itself.
Third, the framework ImageSource
type already has a TypeConverterAttribute
with ImageSourceConverter
as the type converter so everything should work out of the box without having to write a custom converter. Make sure you're not referencing another custom ImageSource
class in another namespace.
To finish, use ImageBrush.ImageSource.AddOwner
rather than redefining a whole new dependency property.
Edit: to answer Berryl's comment:
public static readonly DependencyProperty ImageSourceProperty = ImageBrush.ImageSource.AddOwner(typeof(ImageButton);
This piece of code will reuse the existing ImageSource property rather than defining a new (remember that each different dependency property gets registered in a global static dictionary), only defining a new owner and optionally a new metadata. It's like OverrideMetadata
but from an outside class.