I wonder if anyone can help. I have been banging my head against this problem for half a day now, I must be doing something wrong. I have a custom control with a number of dependency properties.
[TemplatePart(Name = InformationBubble.InformationBubbleTitlePart, Type = typeof(TextBlock))]
[TemplatePart(Name = InformationBubble.InformationBubbleProductImagePart, Type=typeof(Image))]
public class InformationBubble : Control
{
#region Template Parts Name Constants
/// <summary>
/// Name constant for the Information Bubble Title Part
/// </summary>
public const string InformationBubbleTitlePart = "InformationBubbleTitleText";
/// <summary>
/// Name constant for the Information Bubble Product Image Part
/// </summary>
public const string InformationBubbleProductImagePart = "InformationBubbleProductImage";
#endregion
#region TemplateParts
private TextBlock _Title;
internal TextBlock Title
{
get { return _Title; }
private set
{
_Title = value;
if (_Title != null)
{
_Title.Text = this.ProductTitleText;
}
}
}
private Image _ProductImage;
internal Image ProductImage
{
get { return _ProductImage; }
private set
{
_ProductImage = value;
if (_ProductImage != null)
{
_ProductImage.Source = this.ProductImageSource;
}
}
}
#endregion
#region Public String Product Title
// Dependency properties declaration
public static readonly DependencyProperty ProductTitleProperty = DependencyProperty.Register(
"ProductTitle",
typeof(string),
typeof(InformationBubble),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnProductTitleChanged)));
public static void OnProductTitleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
InformationBubble iBubble = sender as InformationBubble;
if (iBubble.Title != null)
{
iBubble.Title.Text = e.NewValue as string;
}
}
public string ProductTitleText
{
get { return GetValue(ProductTitleProperty) as string; }
set { SetValue(ProductTitleProperty, value); }
}
#endregion
#region Public Image Source Product Image
public static readonly DependencyProperty ProductImageSourceProperty = DependencyProperty.Register(
"ProductImageSource",
typeof(ImageSource),
typeof(InformationBubble),
new PropertyMetadata(null, new PropertyChangedCallback(OnProductImageSourceChanged)));
public static void OnProductImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
InformationBubble iBubble = sender as InformationBubble;
if (iBubble.ProductImage != null)
{
iBubble.ProductImage.Source = e.NewValue as ImageSource;
}
}
public ImageSource ProductImageSource
{
get { return GetValue(ProductImageSourceProperty) as ImageSource; }
set { SetValue(ProductImageSourceProperty, value); }
}
#endregion
public InformationBubble()
{
this.DefaultStyleKey = typeof(InformationBubble);
}
#region Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Title = GetTemplateChild(InformationBubble.InformationBubbleTitlePart) as TextBlock;
ProductImage = GetTemplateChild(InformationBubble.InformationBubbleProductImagePart) as Image;
}
#endregion
#region Private Methods
private void GoToState(string stateName, bool useTransitions)
{
VisualStateManager.GoToState(this, stateName, useTransitions);
}
#endregion
}
Now if I use this control somewhere in my xaml it works if I do this:
<controls:InformationBubble
ProductImageSource="{Binding SelectedItem.NormalImageSource}"
ProductTitleText="Test Title"
"/>
But if I try and data bind the product title text to the title property of the SelectedItem object in my ViewModel:
<controls:InformationBubble
ProductImageSource="{Binding SelectedItem.NormalImageSource}"
ProductTitleText="{Binding SelectedItem.Title, Mode=TwoWay"
"/>
I get Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'. The text property of a TextBlock is a DependencyProperty so I must be missing something obvious here.
Could it be that the name of the property is wrong. Should the "ProductTitle" in the code below perhaps be "ProductTitleText"?
public static readonly DependencyProperty ProductTitleProperty = DependencyProperty.Register(
"ProductTitle", // "ProductTitleText" ?
typeof(string),
typeof(InformationBubble),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnProductTitleChanged)));
I imagine that when you use a string constant, then WPF uses reflection to access the property "public string ProductTitleText" directly. The DependencyProperty is ignored, as the name of the property do not match ("ProductTitle" vs. "ProductTitleText").
So for the title you have a dependency property called "ProductTitle" and a (string) property called "ProductTitleText". For the ProductImage you have a dependency property called "ProductImageSource" and a property (of type ImageSource) also called "ProductImageSource".
Does it make sense?