wpf: System.Drawing.Color can't convert from string in XAML (regression)

  • .NET Core Version: 3.1 Preview1 and 3.0 final
  • Windows version: 1809
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: No
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc…)? No

Problem description: When trying to set a property in XAML that is of type System.Drawing.Color, the application fails to convert the XAML.

Actual behavior: Exception: System.Windows.Markup.XamlParseException: ''Set property 'WpfApp3.MyModel.Color' threw an exception.' Line number '10' and line position '10'. Stacktrace:

 	PresentationFramework.dll!System.Windows.Markup.XamlReader.RewrapException(System.Exception e, System.Xaml.IXamlLineInfo lineInfo, System.Uri baseUri)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.WpfXamlLoader.Load(System.Xaml.XamlReader xamlReader, System.Xaml.IXamlObjectWriterFactory writerFactory, bool skipJournaledProperties, object rootObject, System.Xaml.XamlObjectWriterSettings settings, System.Uri baseUri)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.WpfXamlLoader.LoadBaml(System.Xaml.XamlReader xamlReader, bool skipJournaledProperties, object rootObject, System.Xaml.Permissions.XamlAccessLevel accessLevel, System.Uri baseUri)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.XamlReader.LoadBaml(System.IO.Stream stream, System.Windows.Markup.ParserContext parserContext, object parent, bool closeStream)	Unknown
 	PresentationFramework.dll!System.Windows.Application.LoadComponent(object component, System.Uri resourceLocator)	Unknown
>	WpfApp3.dll!WpfApp3.MainWindow.InitializeComponent() Line 1	C#
 	WpfApp3.dll!WpfApp3.MainWindow.MainWindow() Line 25	C#
 	[Native to Managed Transition]	
 	[Managed to Native Transition]	
 	System.Private.CoreLib.dll!System.RuntimeType.CreateInstanceDefaultCtorSlow(bool publicOnly, bool wrapExceptions, bool fillCache) Line 4075	C#
 	System.Private.CoreLib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic, bool wrapExceptions) Line 93	C#
 	System.Private.CoreLib.dll!System.RuntimeType.CreateInstanceImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture) Line 4013	C#
 	System.Private.CoreLib.dll!System.Activator.CreateInstance(System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) Line 34	C#
 	System.Xaml.dll!System.Xaml.Schema.SafeReflectionInvoker.CreateInstanceCritical(System.Type type, object[] arguments)	Unknown
 	System.Xaml.dll!System.Xaml.Schema.XamlTypeInvoker.CreateInstance(object[] arguments)	Unknown
 	System.Xaml.dll!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstanceWithCtor(System.Xaml.XamlType xamlType, object[] args)	Unknown
 	System.Xaml.dll!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args)	Unknown
 	System.Xaml.dll!MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args)	Unknown
 	System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext ctx)	Unknown
 	System.Xaml.dll!System.Xaml.XamlObjectWriter.WriteStartMember(System.Xaml.XamlMember property)	Unknown
 	System.Xaml.dll!System.Xaml.XamlWriter.WriteNode(System.Xaml.XamlReader reader)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.WpfXamlLoader.TransformNodes(System.Xaml.XamlReader xamlReader, System.Xaml.XamlObjectWriter xamlWriter, bool onlyLoadOneNode, bool skipJournaledProperties, bool shouldPassLineNumberInfo, System.Xaml.IXamlLineInfo xamlLineInfo, System.Xaml.IXamlLineInfoConsumer xamlLineInfoConsumer, MS.Internal.Xaml.Context.XamlContextStack<System.Windows.Markup.WpfXamlFrame> stack, System.Windows.Markup.IStyleConnector styleConnector)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.WpfXamlLoader.Load(System.Xaml.XamlReader xamlReader, System.Xaml.IXamlObjectWriterFactory writerFactory, bool skipJournaledProperties, object rootObject, System.Xaml.XamlObjectWriterSettings settings, System.Uri baseUri)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.WpfXamlLoader.LoadBaml(System.Xaml.XamlReader xamlReader, bool skipJournaledProperties, object rootObject, System.Xaml.Permissions.XamlAccessLevel accessLevel, System.Uri baseUri)	Unknown
 	PresentationFramework.dll!System.Windows.Markup.XamlReader.LoadBaml(System.IO.Stream stream, System.Windows.Markup.ParserContext parserContext, object parent, bool closeStream)	Unknown
 	PresentationFramework.dll!System.Windows.Application.LoadBamlStreamWithSyncInfo(System.IO.Stream stream, System.Windows.Markup.ParserContext pc)	Unknown
 	PresentationFramework.dll!System.Windows.Application.LoadComponent(System.Uri resourceLocator, bool bSkipJournaledProperties)	Unknown
 	PresentationFramework.dll!System.Windows.Application.DoStartup()	Unknown
 	PresentationFramework.dll!System.Windows.Application..ctor.AnonymousMethod__1_0(object unused)	Unknown
 	WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)	Unknown
 	WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)	Unknown
 	WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl()	Unknown
 	WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state)	Unknown
 	WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(object obj)	Unknown
 	System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 172	C#
 	System.Private.CoreLib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 132	C#
 	WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
 	WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke()	Unknown
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue()	Unknown
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)	Unknown
 	WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)	Unknown
 	WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o)	Unknown
 	WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)	Unknown
 	WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)	Unknown
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)	Unknown
 	WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)	Unknown
 	[Native to Managed Transition]	
 	[Managed to Native Transition]	
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)	Unknown
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)	Unknown
 	WindowsBase.dll!System.Windows.Threading.Dispatcher.Run()	Unknown
 	PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)	Unknown
 	PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)	Unknown
 	PresentationFramework.dll!System.Windows.Application.Run()	Unknown
 	WpfApp3.dll!WpfApp3.App.Main()	Unknown

Expected behavior: Color gets parsed as in .NET Framework

Minimal repro: Sample repro: WpfApp3.zip Switch target framework to net461 and application runs fine.

Gist: Create this model:

    public class MyModel
    {
        public System.Drawing.Color Color { get; set; }
    }

Assign it in XAML:

    <Grid x:Name="LayoutRoot">
        <Grid.DataContext>
            <local:MyModel Color="Red" />
        </Grid.DataContext>
    </Grid>

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 4
  • Comments: 21 (21 by maintainers)

Most upvoted comments

@dotMorten In the meantime you can use this as a workaround:

 public class MyModel
    {
        [TypeConverter(typeof(System.Drawing.ColorConverter))]
        public System.Drawing.Color Color { get; set; }
    }

It’s not ideal, but it will tell the XAML parser to use that type converter for that specific property. This is a broader issue than just the System.Drawing.Color type and I’ll continue to work on finding a good solution.

We don’t have a strong enough case to bring it back to .NET Core 3.1

I thought regressions from .NET Framework was of high priority? It’ll definitely cause some migration issues for my customers. While work-aroundable, I want to ensure there’s a clean simple migration to .NET Core.

I can actually improve this for Color and others in Drawing.Primitives now. See https://github.com/dotnet/corefx/pull/42300. How important is such a fix? It seems somewhat uncommon for folks to use System.Drawing types when working with WPF, and they could use the workaround.

The parser takes different code paths if it doesn’t find a converter called out via a TypeConverterAttribute. Relying on a “best fit” converter would be a compat break here. This already breaks some tests where it chooses a CollectionConverter for something derived from Collection. But this is unexpected and other parts of the stack pivot on the presence of a converter.

The smallest churn change is to identify a converter that applies directly for the type either via attributes (as before) or ensuring the converter is specific to it. That retains the semantics that we get from looking at the attribute but allows the cases where the attribute is no longer present to succeed.

Anything else I think would have larger implications in both the data binding and xaml parsing stacks.

Color has an intrinsic converter for ColorConverter: https://github.com/dotnet/corefx/blob/18e82cabc1d2cddad8ff07ae96edb7296d9fad9d/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs#L130

Did you try actually getting a converter for color rather than trying to read the attributes yourself? Same is true for any of the intrnsic types. These types live lower in the stack on .NETCore and don’t take a dependency on TypeConverter.