Reputation: 7951
I have a simple problem with the designer.. I'm trying to bind the ItemsSource of a DataGridComboBoxColumn to a list of Enum values. It works, the code compiles and executes just fine. However, the designer says "Problem loading" and will not load properly. If I click "Reload the designer" it shows an error in the Error List. I'm using VS2010.
<ObjectDataProvider x:Key="myEnum"
MethodName="GetValues"
ObjectType="{x:Type core:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type Type="data:ParentClass+MyEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
This works fine when the application executes. However, in the designer it says:
Error 5 Type 'data:ParentClass+MyEnum' was not found.
I'm not sure where I ever came across the Class+Subclass syntax (instead of Class.Subclass) for XAML or why it is necessary, but it would seem the designer should work if the code works?! This kills all my design-time support for my entire window, which is not good if I want to see what changes look like at design time
Update Alright, some more information: First off, the + syntax comes from the Type.GetType(String) method and you can see its formats there.
However, the System.Windows.Markup.TypeExtension uses the IXamlTypeResolver service to resolve the type. From reflector, we can see this:
IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
this._type = service.Resolve(this._typeName);
And from what I understand, the designer uses an entirely different implementation of this service than the runtime?! I haven't located the implementations.
I believe that I could write my own "TypeExtension" class and just do return Type.GetType(typeName). I'm still curious if this is just a bug or a way to make it work.
Update2
I created my own TypeExtension class but it did not help. For some reason Type.GetType() fails to resolve my Enum through the designer (but not runtime)
public class CreateTypeExtension : TypeExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.Type == null)
{
if (this.TypeName == null)
{
throw new InvalidOperationException();
}
this.Type = Type.GetType(TypeName);
if (this.Type == null)
{
throw new InvalidOperationException("Bad type name");
}
}
return this.Type;
}
}
I was passing it
<comm:CreateType TypeName="Company.Product.Class+Enum,Company.Assembly" />
Again, works at runtime and is fully qualified yet it doesn't work at design time.
Upvotes: 3
Views: 466
Reputation: 7951
Alright, I realized that when it didn't work after Update2 that the error message was much more specific than what I was throwing. Therefore, it wasn't using my override. I modified it to not extend TypeExtension and instead MarkupExtension and now it works.
public class CreateTypeExtension : MarkupExtension
{
public Type Type { get; set; }
public String TypeName { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.Type == null)
{
if (this.TypeName == null)
{
throw new InvalidOperationException();
}
this.Type = Type.GetType(TypeName);
if (this.Type == null)
{
throw new InvalidOperationException("Bad type name");
}
}
return this.Type;
}
}
And you can use any format available in the documentation for Type.GetType, but you can no longer use the XAML prefixes (unless you implement this yourself)
<comm:CreateType TypeName="Company.Product.Class+Enum,Company.Assembly" />
Upvotes: 1