views:

34

answers:

1

I am getting this exception when trying to debug a Silverlight 4 application in Visual Studio 2010. The exception will be thrown after it passes the InitializeComponent() line. The exception will only happen during debugging, but it does not seem to be a problem to the Visual Studio Designer.

System.Windows.Markup.XamlParseException occurred
  Message=Failed to create a 'System.Type' from the text 'local:CustomerEntity'. [Line: 11 Position: 59]
  LineNumber=11
  LinePosition=59
  StackTrace:
       at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
       at TestSilverlightApp.MainPage.InitializeComponent()
       at TestSilverlightApp.MainPage..ctor()
  InnerException: 

So what I'm trying to do: I have this ViewModel class that I created which has an EntityType property of type System.Type that will have its value assigned in XAML.

I created a new minimal project that will reproduce the same problem, see below.

MainPage.xaml

This is the RootVisual for the Silverlight application. The ViewModel with the assigned EntityType is declared in the UserControl.Resources.

I also bound the ViewModel to the DataContext and purposely created a Run element in the body that is bound to the EntityType parameter. The Visual Studio Designer has no problem showing the type name of the assigned EntityType.

The error will not occur if I didn't set the EntityType parameter in XAML.

<UserControl x:Class="TestSilverlightApp.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:TestSilverlightApp"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <local:ViewModel x:Key="rootViewModel" EntityType="local:CustomerEntity" />
    </UserControl.Resources>

    <StackPanel x:Name="LayoutRoot" DataContext="{StaticResource rootViewModel}">
        <TextBlock><Run Text="{Binding EntityType}" /></TextBlock>
    </StackPanel>
</UserControl>


MainPage.xaml.cs

This exception will be thrown after it passes the InitializeComponent() line below.

namespace TestSilverlightApp
{
    public partial class MainPage : System.Windows.Controls.UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}


ViewModel.cs

The ViewModel class has an EntityType property which accepts System.Type value.

namespace TestSilverlightApp
{
    public class ViewModel
    {
        public System.Type EntityType { get; set; }
    }
}


CustomerEntity.cs

This is just an empty class that I created for the purpose of assigning its Type to the ViewModel.EntityType property.

namespace TestSilverlightApp
{
    public class CustomerEntity
    { }
}


Any idea on how I can fix this? I prefer to not implement my own TypeConverter or something to set a System.Type value in XAML.

A: 

Here is a type converter you can use:-

public class TypeTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(System.Type);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {

        return Type.GetType((string)value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        return value.ToString();  
    }
}

In you view model code use:-

public class ViewModel  
{
    [TypeConverter(typeof(TypeTypeConverter))]  
    public System.Type EntityType { get; set; }  
}

You can't use namespace aliases to define the type, it has to be a type that the static GetType method recognises:-

<local:ViewModel x:Key="rootViewModel" EntityType="TestSilverlightApp.CustomerEntity" />
AnthonyWJones
Already done the exact same thing. It's working during runtime, but the designer will give me a parsing error for the whole block saying "Invalid format for a type." and Visual Studio will then refuse to load the whole designer until I change it back to the "xmlns:TypeName" format.
Amry
@Amry: The problem is that the designer is pretty much the same whether you are developing a WPF or Silverlight app. It makes loads of assumptions that aren't necessarily true at runtime. Hence what works at runtime doesn't always work at design time and vice versa. I'll see if I can come up with an alternative.
AnthonyWJones
@Anthony: Yes, I'm aware of that. However what I'm trying to achieve in the end is a component that will be reused by other developers in the team. Having said that, it's not acceptable for the other developers not to be able to use the designer for whatever reason, that would reduce their productivity. :)
Amry