wpftoolkit
wpftoolkit copied to clipboard
ArgumentOutOfRangeException in validation
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.
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