Hints on fighting the dreaded crash in XcpImports.MethodEx
In programming for Silverlight platform, one commonly encountered problem is a crashing with an error like:
Message: Unhandled Error in Silverlight 2 Application Value does not fall within the expected range.
at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData)
at System.Windows.DependencyObject.MethodPack(IntPtr objectPtr, String methodName, Object[] rawData)
at System.Windows.DependencyObject.MethodPack(String methodName, Object[] rawData)
at System.Windows.UIElement.TransformToVisual(UIElement visual)
at System.Windows.Controls.ListBox.IsOnCurrentPage(Object item, Rect& itemsHostRect, Rect& listBoxItemRect)
at System.Windows.Controls.ListBox.ScrollIntoView(Object item)
at System.Windows.Controls.ListBox.NotifyListItemClicked(ListBoxItem listBoxItem)
at System.Windows.Controls.ListBoxItem.OnMouseLeftButtonDown(MouseButtonEventArgs e)
at System.Windows.Controls.ListBoxItem.<.ctor>b__0(Object sender, MouseButtonEventArgs e)
at System.Windows.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)
The lower part of stack trace may change: the error may come from different controls, but the call to UIElement.TransformToVisual is the thing that is common for this kind of crashes. There's a lot of discussions - sometimes pretty confusing - about this issue (for example, see this, this and this), but no clear guide of how to handle this matter. Here I'm trying to summarize our experience with different incarnations of this problem, hope it will be helpful.
Why it happens? Basically, it happens when you're trying to do something with currently invisible control. Of course, the error message should be more clear than that, but alas, the similar words could be said about many things in Silverlight. So the recommendations are:
1. Unsubscribe invisible controls from data events wherever possible. For example, if you are hiding your ChildWindow, always make sure that it doesn't listen to INotifyPropertyChanged, INotifyPropertyChanging and INotifyCollectionChanged events any more. It shouldn't. This crash is the first indication you are doing something wrong with event subscription.
2. Try to separate observable data for visible and invisible controls. For example, if you're having two tabs listening to the same collection, you'll get this error sooner or later: your invisible control will be trying to react on the changing data, but there's no need for that, as it is invisible anyway. So the right approach is to use separate collection for first and second control, and synchronize them only when the visibility state has actually changed.
3. Use Dispatcher. Sometimes your control just isn't fast enough to react to your changes, and you'll be getting this error even if it must be already visible. Wrapping your selection-related code into Dispatcher.BeginInvoke(delegate() {...}) seems to solve this issue, even if you are not doing anything in the background thread and just changing the visibility state of your controls.
Of course this is not all, but may be helpful in many cases.
