locked
"Error: Converter failed to convert value of type" when type is derived RRS feed

  • Question

  • I have the following code:

    public sealed partial class BlankPage
    {
        public HolderObject HolderObject { get; set; }
            
        public BlankPage()
        {
            InitializeComponent();
    
            HolderObject = new HolderObject();
    
            DataContext = this;
        }
    }
    public class HolderObject
    {
        public ParentObject SelectedObject
        {
            get { return new ChildObject(); }
        }
    }
    public abstract class ParentObject
    {
    }
    public class ChildObject : ParentObject
    {
    }
    
    public sealed partial class DescriptionViewer
    {
        public static readonly DependencyProperty HolderProperty =DependencyProperty.Register("Holder", typeof(ParentObject), typeof(DescriptionViewer),new PropertyMetadata(null));
        public ParentObject Holder
        {
            get { return (ParentObject)GetValue(HolderProperty); }
            set { SetValue(HolderProperty, value); }
        }
        public DescriptionViewer()
        {
            InitializeComponent();
        }
    }

    and xaml:

    <Page
        x:Class="Application1.BlankPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Application1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
            <local:DescriptionViewer Holder="{Binding HolderObject.SelectedObject}"/>
    
        </Grid>
    </Page>

    Now, as you can imagine HolderObject.SelectedObject gets called by the debugger when trying to bind it to the holder property.

    However, then an error appears in the output window:
    Error: Converter failed to convert value of type 'Application1.ChildObject, Application1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' to type 'ParentObject'; BindingExpression: Path='HolderObject.SelectedObject' DataItem='Application1.BlankPage'; target element is 'Application1.DescriptionViewer' (Name='null'); target property is 'Holder' (type 'ParentObject').

    This of course makes no sense, because ChildObject is derived from ParentObject, so it simply needs to cast it, which automatically happens in both WPF and Silverlight.  Even if I build a converter to try and return it as ParentObject, the same problem still happens.

    What can I do to work around this? It is quite a major problem for me.

    Stefan

    Thursday, April 19, 2012 1:51 AM

Answers

  • Hi Stefan, this is because the system has no metadata about the types.  ChildObject would need to be used in XAML somewhere so that the code generation automatically gets generated for the type and dependencies (XamlTypeInfo).  When this happens, then this should work.  You can also provide your own implementation of IXamlMetadataProvider to provide this information but the easiest/fastest thing to do is add a page to your app and add <local:ChildObject /> to it.  This will trigger it to be code generated and your other path should work now.  This page doesn't have to be used in your app, just existing as Page so it participates in code generation.  Again, providing your own IXamlMetadataProvider, but this is also another way that is fast.

    Tim Heuer | Program Manager, XAML | http://timheuer.com/blog | @timheuer

    (if my post has answered your question, please consider using the 'mark as answer' feature in the forums to help others)

    Tuesday, July 10, 2012 5:11 PM

All replies

  • Stefan - I couldn't get the code to work. Can you send me a sample project?  MSMALL at Microsoft.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator


    Tuesday, April 24, 2012 3:45 PM
    Moderator
  • Thanks Matt, have just e-mailed you a reproducible sample.
    Tuesday, April 24, 2012 8:06 PM
  • This is NOT fixed in RP.  This is quite a major problem, because I have to write a lot of extra code, sometimes with complex hacks and the risk of memory leaks.  Is this going to be fixed by RTM?

    ...Stefan

    Wednesday, June 6, 2012 2:44 AM
  • Hi,

    while converting from Silverlight to Metro I also notice this problem and it is a real pain. I change property type to object and add additional property with casting... it works, but I hope it will be solved in RTM...

    edvin

    Thursday, June 7, 2012 1:06 PM
  • Stefan - do you have an app updated for RP that I can have?

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    Tuesday, June 12, 2012 3:30 PM
    Moderator
  • Yup, just e-mailed one to you.
    Tuesday, June 12, 2012 6:18 PM
  • I hope this is now acknowledged as an issue.

    In my case I have a custom attached property of type ICollection<ValidationResult>, and it gets data-bound to an indexed property of type ICollection<ValidationResult>, but the runtime type is obviously a concrete class, in my case it is List<ValidationResult>.

    I get the error "Converter failed to convert value of type 'System.Collections.Generic.List`1[[System.ComponentModel.DataAnnotations.ValidationResult, System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' to type 'ValidationResult>'; BindingExpression: Path='Message.ErrorMap[Comments]' DataItem='Canesto.Portal.Worker.Metro.Data.MessageItem, Canesto.Portal.Worker.Metro, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; target element is 'Windows.UI.Xaml.Controls.TextBox' (Name='null'); target property is 'Errors' (type 'ValidationResult>').

    (Note, the error message is faulty as well - look at the end of it.)

    When I change the attached property type to List<ValidationResult> it starts working, though intuitively it should rather not, as I am now assigning an ICollection<T> to a List<T> (as far as static type declarations are concerned).

    Regards,

    Karl

    Thursday, July 5, 2012 2:05 PM
  • Yes, I have filed a bug on this.  Hopefully will get fixed by RTM.

    Stefan

    Thursday, July 5, 2012 7:41 PM
  • Hi Stefan, this is because the system has no metadata about the types.  ChildObject would need to be used in XAML somewhere so that the code generation automatically gets generated for the type and dependencies (XamlTypeInfo).  When this happens, then this should work.  You can also provide your own implementation of IXamlMetadataProvider to provide this information but the easiest/fastest thing to do is add a page to your app and add <local:ChildObject /> to it.  This will trigger it to be code generated and your other path should work now.  This page doesn't have to be used in your app, just existing as Page so it participates in code generation.  Again, providing your own IXamlMetadataProvider, but this is also another way that is fast.

    Tim Heuer | Program Manager, XAML | http://timheuer.com/blog | @timheuer

    (if my post has answered your question, please consider using the 'mark as answer' feature in the forums to help others)

    Tuesday, July 10, 2012 5:11 PM
  • Is adding the derived class to a page still a valid solution to this problem?  I tried adding it to a page and got the following error:

    "The specified value cannot be assigned to this collection.  The following type was expected: "UIElement".

    So I moved it to the page resources which resolved this error but I still get the conversion error noted by Stefan above.


    Follow me on Twitter - @chief7

    Friday, August 31, 2012 10:46 AM
  • Hi everyone,

    I was able to solve the problem using Tim Heuer's advice.  Here's what I did:

    1. Add a public parameterless constructor to the derived type, if it doesn't already have a default constructor. *
    2. Add a new page to your project using the Blank Page item template in Visual Studio.  I added mine in a folder named Resources and named it MyTypeNameTypeInfo.xaml.  Of course, MyTypeName is my actual type's name.
    3. Delete the code behind file that Visual Studio generated for the page.  If it's VB.NET then you may need to Show All Files first, though I haven't tried it myself.
    4. Replace the entire contents of MyTypeNameTypeInfo.xaml with the following.  Don't forget to replace MyTypeName and MyNamespace with your real names.
      <local:MyTypeName xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:local="using:MyNamespace" />
    5. Make sure that the page's Build Action in the Properties window is set to Page.

    That's it.  Not ideal, but it worked for me.  At least the page is under a Resources folder, so I don't have to look at it :)

    - Dave

    * I don't want to have a default constructor on my particular type, so I simply throw NotSupportedException just in case I accidently try to use it one day. This doesn't appear to conflict with Tim's solution because the page in which it's added is never actually used in the application, thus the constructor is never actually invoked.


    http://davesexton.com/blog

    Friday, April 5, 2013 8:00 PM
  • I've had problems when using dependency properties of type List<objecttypegoeshere>.  I haven't found a workaround other than setting the type the dependency property to object. This is really pretty bad, and completely different than the other XAML technologies.

    Stefan

    Friday, April 5, 2013 8:07 PM