PropertyGrid Errors

Grids for WPF Forum

Posted 7 years ago by Rick - Developer, Visual Software Systems LLC
Version: 17.1.0650
Platform: .NET 4.5
Environment: Windows 10 (64-bit)
Avatar

I've just upgraded my project to WPF Studio 2017.1. Wow, what a great update!  I love the new Tree Controls and the updated PropertyGrid is lightning fast.  After the updgrade to use the 2017.1 version of PropertyGrid, I started seeing two issues I hadn't had with the 2016 version.

In my app, the PropertyGrid is bound to a TreeView control's SelectedItem property via XAML. When a node is expanded for the first time, a background worker makes a service call to populate the node's children and update some properties of the object the node is bound to. 

Issue 1) If I expand a previously unexpanded node while the PropertyGrid is bound to it, the following error is thrown:

System.InvalidOperationException occurred
  HResult=0x80131509
  Message=The calling thread cannot access this object because a different thread owns it.
  Source=WindowsBase
  StackTrace:
   at System.Windows.Threading.Dispatcher.VerifyAccess()
   at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
   at ActiproSoftware.Windows.Controls.Grids.TreeListBox.get_ItemAdapter()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#4Aj(String #ovd)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#3Aj(Object #xhb, PropertyChangedEventArgs #yhb)
   at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
   at ActiproSoftware.Windows.ObservableObjectBase.OnPropertyChanged(PropertyChangedEventArgs e)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.PropertyModelBase.OnPropertyChanged(PropertyChangedEventArgs e)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.CachedPropertyModelBase.OnPropertyChanged(PropertyChangedEventArgs e)
   at ActiproSoftware.Windows.ObservableObjectBase.NotifyPropertyChanged(String propertyName)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.PropertyModelBase.#QOj()
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.PropertyModelBase.Refresh(PropertyRefreshReason reason)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.PropertyDescriptorPropertyModel.OnPropertyValueChanged(Object #xhb, EventArgs #yhb)
   at System.ComponentModel.PropertyDescriptor.OnValueChanged(Object component, EventArgs e)
   at System.ComponentModel.ReflectPropertyDescriptor.OnValueChanged(Object component, EventArgs e)
   at System.ComponentModel.ReflectPropertyDescriptor.OnINotifyPropertyChanged(Object component, PropertyChangedEventArgs e)
   at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
   at SOQLStudio.Organization.NotifyPropertyChanged(String propertyName) in P:\SOQL Studio\SOQL Studio\SOQLStudio\Classes\Organization.vb:line 66

This is a new behavior in the 2017 version.  In the 2016 version, it didn't matter if the tree node was selected or not.

Issue 2)  I get the following error when I select certain child nodes in the tree.  The error is consistant in that it happens with the same nodes, but only a few nodes trigger it (so it's data-related in some way):

System.InvalidOperationException occurred
  HResult=0x80131509
  Message=Failed to compare two elements in the array.
  Source=<Cannot evaluate the exception source>
  StackTrace:
   at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
   at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
   at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.DataFactoryBase.SortDataModels(IList`1 models, IDataFactoryRequest request, DataModelSortComparer sortComparer)
   at ActiproSoftware.Windows.Controls.Grids.PropertyData.DataFactoryBase.GetDataModels(IDataFactoryRequest request)
   at ActiproSoftware.Windows.Controls.Grids.PropertyGridItemAdapter.#TMj(PropertyGrid #gCb, IDataModel #SMj)
   at ActiproSoftware.Windows.Controls.Grids.PropertyGridItemAdapter.GetChildren(TreeListBox ownerControl, Object item)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#GM()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#fBj(Boolean #6zj)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#0Dj()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.get_IsExpandable()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#bBj()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#WDj(#LDj #SDb, Boolean #XDj)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#9Aj(IEnumerable #aBj)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#njb(IEnumerable #Ld, Boolean #BCf)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#rBj(IEnumerable #Ld)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#GM()
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#7Aj(Boolean #Ld, TreeListBoxItemAdapter #6Aj, TreeExpansionKind #GAf, Object #BEf)
   at ActiproSoftware.Windows.Controls.Grids.TreeListBox.GetOrCreateTreeNode(TreeNode parentTreeNode, Object item, Boolean allowCreate)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#9Aj(IEnumerable #aBj)
   at ActiproSoftware.Windows.Controls.Grids.Primitives.TreeNode.#njb(IEnumerable #Ld, Boolean #BCf)
   at ActiproSoftware.Windows.Controls.Grids.TreeListBox.ResetItemsSource()
   at ActiproSoftware.Windows.Controls.Grids.TreeListBox.OnRootItemPropertyValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at ActiproSoftware.Windows.Controls.Grids.TreeListBox.set_RootItem(Object value)
   at ActiproSoftware.Windows.Controls.Grids.PropertyGrid.Refresh()
   at ActiproSoftware.Windows.Controls.Grids.PropertyGrid.<>c__DisplayClass64_0.<RequestRefresh>b__0()
   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)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(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)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at SOQLStudio.Application.Main()

Inner Exception 1:
ArgumentOutOfRangeException: Index and length must refer to a location within the string.

 Again, this is a new behavior in the 2017 version.  I didn't have this problem with the 2016 version of PropertyGrid. And I really don't know where  to start with this one.

Any help you can provide with these two issues is greatly appreciated.

Thanks... Rick

Comments (7)

Posted 7 years ago by Rick - Developer, Visual Software Systems LLC
Avatar

Update on Issue1:  I was able to solve this by moving all NotifyPropertyChanged calls out of the background worker's DoWork method and into the RunWorkerCompleted method.  Should have coded it this way to begin with but sometimes it's not immediately obvious (to me anyway) that the UI thread will reference a piece of data that the background thread is currently modifying.

Issue 2 still has me perplexed, though...

Rick

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Rick,

I'm glad the new PropertyGrid is working much faster for you.  That's what we've seen too.

These are things we'd probably need to see a sample project for and use it to debug them.  Can you throw together a new very simple sample project that shows them both and we'll use that to sort out the problems and ensure they are resolved for the next build?  Please send the sample to our support address and rename the .zip file extension of what you send so it doesn't get spam blocked. 

The first issue is a cross thread one.  As you saw, the background service updates you were doing were causing the property grid to try and update itself in the same thread.  Thus we need to probably watch for that and use a Dispatcher.Invoke when the scenario is detected.  Even though you fixed it in your app, the sample would help us compare the new version logic to the old one in that scenario and see why it worked in the old one.

The second issue is something in the property grid data model sorting logic, but it's hard to say without being able to debug it.

Thanks!


Actipro Software Support

Posted 7 years ago by Rick - Developer, Visual Software Systems LLC
Avatar

I will try to put together a sample project that illustrates both issues.  For now, I've turned off sorting.  I'm not sure it was really doing anything for me as all the results are appearing in the order that I want.  Actually, I'm getting better results with child array elements being presented in numerical order ([0], [1], [2], etc.) rather than in alphabetical order ([0], [1], [10], [11], ...[2], [21], etc.)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Rick,

We actually have code in there that is intended to sort those index kinds of item display names properly, and at a higher priority than normal pure alpha sorting.  I wonder if that is related to this issue and perhaps there's some bug in that area for #2?


Actipro Software Support

Posted 7 years ago by Rick - Developer, Visual Software Systems LLC
Avatar

I'm wondering that too.  To test, I turned sorting back on and set CanCompareIndex = False.  No error is thrown with this configuration.  Further, I think I've narrowed the condition down to the simple array having 100 or more elements in it.  I'm working on proving that theory now.

Posted 7 years ago by Rick - Developer, Visual Software Systems LLC
Avatar

I've confirmed that the error is directly related to the number of elements in the child array.  The sorting works with 100 or less elements.  Add 1 more and the exception is thrown.

And when there's less than 101 items, sorting is inconsistant.  I can send you some screen captures that illistrate it, if you want.

 

Rick

[Modified 7 years ago]

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Rick,

Yes good find!  There was a variable reference bug in the DataModelSortComparer.CompareIndex method.  Fixing that resolves the exception (your second issue) and the sort order being incorrect.  The fix will be in the next build.

If you can wrap up a quick sample for the original first issue, we can look into that too.  Thanks!


Actipro Software Support

The latest build of this product (v24.1.2) was released 2 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.