Search code examples
c#arrayswpfpropertygridxceed

Xceed PropertyGrid with System.Windows.Media.Color[] throws NullReferenceException


I have an object that I'm trying to use with a PropertyGrid and it throws a NullReferenceException when trying to access the Color[] property.

The stack trace looks like:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Xceed.Wpf.Toolkit.CollectionControlDialog.Clone(Object source) in C:\Users\brian\Documents\Visual Studio 2015\Projects\FevDnDTester\ExtendedWPFToolkitSolution\Src\Xceed.Wpf.Toolkit\CollectionControl\Implementation\CollectionControlDialog.xaml.cs:line 168
   at Xceed.Wpf.Toolkit.CollectionControlDialog.OnSourceInitialized(EventArgs e) in C:\Users\brian\Documents\Visual Studio 2015\Projects\FevDnDTester\ExtendedWPFToolkitSolution\Src\Xceed.Wpf.Toolkit\CollectionControl\Implementation\CollectionControlDialog.xaml.cs:line 137
   at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
   at System.Windows.Window.CreateSourceWindowDuringShow()
   at System.Windows.Window.SafeCreateWindowDuringShow()
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Window.Show()
   at System.Windows.Window.ShowDialog()
   at Xceed.Wpf.Toolkit.CollectionControlButton.CollectionControlButton_Click(Object sender, RoutedEventArgs e) in C:\Users\brian\Documents\Visual Studio 2015\Projects\FevDnDTester\ExtendedWPFToolkitSolution\Src\Xceed.Wpf.Toolkit\CollectionControl\Implementation\CollectionControlButton.cs:line 124
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

As you can see, there is nothing related to my own code so this must be a fairly common error. It looks like it is trying to clone my array of Color objects and failing, but the array and none of the objects inside are null.

Any thoughts?


Solution

  • This is a bug in the CollectionControlDialog class.

    In the method Clone(), they obtain the type of the provided collection item and then try to invoke a default constructor of that type. I suppose, they want to create a deep copy of each collection item.

    But obviously, a struct Color have no default constructor (as a method) which could be obtained via reflection. (The default parameterless constructor you could use on a struct isn't actually a constructor, but it's an IL instruction for the runtime how to create a default instance of the struct).

    So that's why the GetConstructor() method returns null, and attempt to invoke a method on a null throws the NullReferenceException you observe.

    You could list a bug or fix it by yourself and commit to the Xceed repository.

    Currently, this bug prevents you from being able to use the CollectionControlDialog with such objects that do not have a default parameterless constructor (like structs or some classes too).