xceedsoftware / wpftoolkit

All the controls missing in WPF. Over 1 million downloads.
Other
3.91k stars 878 forks source link

ArgumentOutOfRangeException in validation #1662

Open billw2012 opened 3 years ago

billw2012 commented 3 years ago
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
   at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   at System.ThrowHelper.ThrowArgumentOutOfRangeException()
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at System.Collections.ObjectModel.Collection`1.get_Item(Int32 index)
   at System.Collections.ObjectModel.ReadOnlyCollection`1.get_Item(Int32 index)
   at Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem.<>c__DisplayClass33_0.<SetRedInvalidBorder>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.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)

The problem is fairly clear here:

https://github.com/xceedsoftware/wpftoolkit/blob/61789cfce1669938d8b38e9c265304d095a0a239/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.Toolkit/PropertyGrid/Implementation/PropertyItem.cs#L231

The code assumes that the errors can't be cleared between when the check is done and when they are read, whereas the apparently can. As the code that actually retrieves the errors (Validation.GetErrors) is inside the dispatched invoke there is significant opportunity for the state to change, which results in this crash.

I reproduced this just by clearing the contents of a float edit control that had a Default value set via attribute in the Property Grid. I presume some logic is restoring the default between when the HasErrors and GetErrors code is run.

XceedBoucherS commented 3 years ago

Hi, This issue is already fixed. The fix will appear in v4.2. In the meantime, you can replace the content of method SetRedInvalidBorder to: if( ( be != null ) && be.DataItem is DescriptorPropertyDefinitionBase ) { this.Dispatcher.BeginInvoke( DispatcherPriority.Input, new Action( () => { DescriptorPropertyDefinitionBase descriptor = be.DataItem as DescriptorPropertyDefinitionBase; if( ( descriptor != null ) && Validation.GetHasError( descriptor ) ) { var errors = Validation.GetErrors( descriptor ); Validation.MarkInvalid( be, errors[ 0 ] ); } } ) ); }

Thank you