Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'
Asked Answered
D

3

6

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.

Delphadelphi answered 23/5, 2011 at 16:37 Comment(1)
I agree with Ole, you seem to have a typo when you register you dependency property. Just a note, you can use the snippet for dependency property creation which is propdp tab tab. That should help in the future :)Egoist
H
10

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?

Hampson answered 23/5, 2011 at 16:42 Comment(2)
But it works using a string value, it's only when I try and data bind to the object in the ViewModel that it fails.Delphadelphi
I knew it would be something simple! Many thanks for your help. I never new the names had to match up, but obviously this is important when databinding. The fact I could apply a string value threw me!Delphadelphi
M
0

You can also get this error when the ownerType of the DependencyProperty is incorrect.

public static readonly DependencyProperty ProductTitleProperty = DependencyProperty.Register(
    "ProductTitle",
    typeof(string),
    typeof(SomeOtherType), // In my case, this was the wrong type.
    new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnProductTitleChanged)));

(This can happen when you copy and paste the same DependencyProperty between classes.)

Mutate answered 10/3, 2022 at 20:3 Comment(0)
E
0

You can also get this error if the name of the DepencendyProperty is not exactly the name of the property implementing get/set, with the suffix Property

public static readonly DependencyProperty MyPropertyNameProperty = [...]
public string MyPropertyName // in my case, this was a different name
{
    get { return GetValue(MyPropertyName) as string; }
    set { SetValue(MyPropertyName, value); }
}
Englishry answered 21/12, 2023 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.