Specified argument was out of range of valid values

Topics: Prism v4 - Silverlight 4
Jan 23, 2011 at 3:06 PM

Hello,

I'm working on an app where I load views into regions when a user logs in.  Then I want to unload everything when they log off.

There doesn't appear to be a way to unload modules so I'm just going to unload views for the module.

Here is a snippet of the code that is throwing an exception.

IRegion _rootTab = _regionManager.Regions[RegionNames.RootRibbonTabRegion];
            object _view = _regionManager.Regions[RegionNames.RootRibbonTabRegion].GetView(ReflectionUtility.GetPropertyName(() => _credentialsRootRibbonTabView));
            _rootTab.Remove(_view);

 

The credentialsRootRibbonTabView is present in the region and what's funny, even though an exception is being thrown when _rootTab.Remove is called, when I look at the Views for the region, it's actually removed.  So it's like the remove is removing the view correctly but then it's trying to do something else in the View collection at a certain index, however, in this case after the Remove() endpoint, remove's this view, there are no more views in the RegionNames.RootRibbonTabRegion region.  So again behind the scenes there looks as if there is a problem somewhere in Prism that is trying to do something with an index in a collection that has no elements anymore after the remove.

Below is the stack at the time of the crash.  It looks like a generic stack you'd expect in a scenario trying to access an element of a collection outside the valid indexes contained in the collection.

Again, the issue is, this view is present before I all Remove() and Remove is actually removing the View from the collection as it should but Remove is excepting for some reason.

Any ideas of how to work around this.  FYI, the type of Region is AllActive.

Thanks.

 

 

 

 

   at System.Windows.PresentationFrameworkCollection`1.GetItemDependencyObject(Int32 index)
   at System.Windows.Controls.UIElementCollection.GetItemImplSkipMethodPack(Int32 index)
   at System.Windows.Controls.ItemsControl.RemoveContainerForPosition(GeneratorPosition position)
   at System.Windows.Controls.ItemsControl.OnItemsChangedHandler(Object sender, ItemsChangedEventArgs args)
   at System.Windows.Controls.Primitives.ItemsChangedEventHandler.Invoke(Object sender, ItemsChangedEventArgs e)
   at System.Windows.Controls.ItemContainerGenerator.RemoveItem(Object item, Int32 itemIndex, DependencyObject container, Int32 containerCount, GeneratorPosition position, ItemBlock block, Int32 offsetFromBlockStart, Boolean raiseReplaceInsteadOfRemove)
   at System.Windows.Controls.ItemContainerGenerator.OnItemRemoved(Object item, Int32 itemIndex, Boolean raiseReplaceInsteadOfRemove)
   at System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.ICollectionChangedListener.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.WeakCollectionChangedListener.SourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.ItemCollection.NotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.ItemCollection.System.Windows.Controls.ICollectionChangedListener.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.ItemCollection.EnumerableCollectionView.System.Windows.Controls.ICollectionChangedListener.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.WeakCollectionChangedListener.SourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at Microsoft.Practices.Prism.Regions.ViewsCollection.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at Microsoft.Practices.Prism.Regions.ViewsCollection.NotifyRemove(IList items, Int32 originalIndex)
   at Microsoft.Practices.Prism.Regions.ViewsCollection.RemoveFromFilteredList(Object item)
   at Microsoft.Practices.Prism.Regions.ViewsCollection.SourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32 index)
   at System.Collections.ObjectModel.Collection`1.Remove(T item)
   at Microsoft.Practices.Prism.Regions.Region.Remove(Object view)
   at AuthenticatorSL.Modules.Credentials.CredentialController.CleanUp(Object o)
   at GalaSoft.MvvmLight.Helpers.WeakAction`1.Execute(T parameter)
   at GalaSoft.MvvmLight.Helpers.WeakAction`1.ExecuteWithObject(Object parameter)
   at GalaSoft.MvvmLight.Messaging.Messenger.SendToList[TMessage](TMessage message, IEnumerable`1 list, Type messageTargetType, Object token)
   at GalaSoft.MvvmLight.Messaging.Messenger.SendToTargetOrType[TMessage](TMessage message, Type messageTargetType, Object token)
   at GalaSoft.MvvmLight.Messaging.Messenger.Send[TMessage](TMessage message)
   at AuthenticatorSL.Infrastructure.GlobalAppCommands.LogoutCommand.Send(LogoutEvent evt)
   at AuthenticatorSL.Modules.Credentials.CredentialsRootRibbonQATBVM.<get_LogOffCommand>b__2()
   at GalaSoft.MvvmLight.Command.RelayCommand.Execute(Object parameter)
   at Telerik.Windows.Controls.RadButton.ExecuteCommand()
   at Telerik.Windows.Controls.RadButton.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

Jan 23, 2011 at 5:27 PM
Edited Jan 23, 2011 at 5:59 PM

Ok, so you have a region adapter for Telerik RadRibbon control, now when you are removing an object from the region you get an out of index.  i see you are using MVVMLight as your mvvm glue.  May I ask why you are choosing to use reflection to find the view name that is to be removed, just seems like alot of overhead to simply pass in a string name. Its not like you don't have knowledge of the view (just have me scratching my head, that is all).  Secondly are you sure its passing in the right name and your sure the object view in question is in the region in question with the name in question.

One thing I do when I getting the View in the manner is to make sure that the view isn't null before I attempt to remove it or deactivate it.

Edit: There might also be something wrong with region adapter not working correctly too on the removals.

Morgan.

Jan 23, 2011 at 5:32 PM
Edited Jan 23, 2011 at 6:08 PM
mvermef wrote:

May I ask why you are choosing to use reflection to find the view name that is to be removed, just seems like alot of overhead to simply pass in a string name. Its not like you don't have knowledge of the view (just have me scratching my head, that is all). 

Because that's just the last avenue I've tried to get it to work.  I've tried using it with the actual view and changed to that as part of the troubleshooting process. 

This is how it would be normally.

_credentialRegionManager.Regions[RegionNames.RootRibbonTabRegion].Remove(_credentialsRootRibbonTabView)

As far as custom RegionAdapters, I have one for the QuickAccessToolBar but not one specifically for the RibbonControl.  The RibbonControl contains a lot of different controls such as Tab, Toolbar etc.

Nothing in my code adapter appears to run at the time of the exception.

Here is the xaml for the RibbonBar.

<telerik:RadRibbonBar Grid.Row="0" ApplicationName="Authenticator - www.n-stech.com" IsMinimized="False" Margin="0" 
                              Regions:RegionManager.RegionName="{Binding RegionNames.RootRibbonTabRegion, Source={StaticResource ResourceWrapper}}"
                              HorizontalContentAlignment="Stretch"
                              VerticalContentAlignment="Stretch"
                              HelpButtonVisibility="Visible"
                              ApplicationButtonVisibility="Visible"
                             
                             
                              >
            <telerik:RadRibbonBar.QuickAccessToolBar>
                <telerik:QuickAccessToolBar x:Name="RootQATBRegion"
                                            Regions:RegionManager.RegionName="{Binding RegionNames.RootQATBRegion, Source={StaticResource ResourceWrapper}}"  
                                            >

                </telerik:QuickAccessToolBar>
            </telerik:RadRibbonBar.QuickAccessToolBar>
            <telerik:RadRibbonBar.ApplicationMenu>
                <telerik:ApplicationMenu x:Name="RootApplicationMenuRegion" Regions:RegionManager.RegionName="{Binding RegionNames.RootApplicationMenuRegion, Source={StaticResource ResourceWrapper}}" >
                </telerik:ApplicationMenu>
            </telerik:RadRibbonBar.ApplicationMenu>           
        </telerik:RadRibbonBar>

 

Jan 23, 2011 at 6:05 PM

ok.

 

Did you write the adapter yourself? Have to you tried trapping for null values before trying to remove the view object?

Here is a snippet of some of my code for deactivation and subsequent removal

 var view = regionManager.Regions[RegionNames.PopupRegion].GetView("EditFlightsView");
            
            if (view != null)
            {                
                regionManager.Regions[RegionNames.PopupRegion].Deactivate(view);
                regionManager.Regions[RegionNames.PopupRegion].Remove(view);
                Flight = null;
                view = null;                
            }
Don't think its a PRISM issue, I would gravitate towards issues with the adapter used.

Jan 23, 2011 at 6:16 PM

Yes I wrote the QATB adapter but it only pertains to one section of the RibbonBar.

I've set break points in my the adapter code I have and nothing fires in it.

Also, I'm never setting the Views to null, I'm just removing them.  I have tried to use Deactive as you have above, that causes an exception.

Deactivation is not possible in this type of region.  (That's why I mentioned this was an AllActiveRegion earlier.)

   at Microsoft.Practices.Prism.Regions.AllActiveRegion.Deactivate(Object view)
   at AuthenticatorSL.Modules.Credentials.CredentialController.CleanUp(Object o)
   at GalaSoft.MvvmLight.Helpers.WeakAction`1.Execute(T parameter)
   at GalaSoft.MvvmLight.Helpers.WeakAction`1.ExecuteWithObject(Object parameter)
   at GalaSoft.MvvmLight.Messaging.Messenger.SendToList[TMessage](TMessage message, IEnumerable`1 list, Type messageTargetType, Object token)
   at GalaSoft.MvvmLight.Messaging.Messenger.SendToTargetOrType[TMessage](TMessage message, Type messageTargetType, Object token)
   at GalaSoft.MvvmLight.Messaging.Messenger.Send[TMessage](TMessage message)
   at AuthenticatorSL.Infrastructure.GlobalAppCommands.LogoutCommand.Send(LogoutEvent evt)
   at AuthenticatorSL.Modules.Credentials.CredentialsRootRibbonQATBVM.<get_LogOffCommand>b__2()
   at GalaSoft.MvvmLight.Command.RelayCommand.Execute(Object parameter)
   at Telerik.Windows.Controls.RadButton.ExecuteCommand()
   at Telerik.Windows.Controls.RadButton.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

Jan 23, 2011 at 7:08 PM
Edited Jan 23, 2011 at 7:11 PM

If nothing fires in your adapter at all for when you add stuff to the region, is it registered.  Just trying to see if everything is in place for the adapter to do its work.

yeah wasn't trying to suggest that you use Deactivate on an AllActiveRegion

I have run into situation when I didn't add my infrastructure to the composition (MEF), that had the adapter and was confusing me cause i thought it was registered (tongue in cheek, when I finally figured it out). 

Jan 23, 2011 at 7:21 PM

Keep in mind, my adapter is just so I can add buttons to the RibbonBar's QuickAccessToolbar.  Most of the other parts of the RibbonBar work with the Prism's built in RegionAdapters.  The Region for which I'm trying to remove a view from is using one of Prism's built in RegionAdapters.

I register the QATB adapter in the boot strapper and yes it works when I add items to it.

My comments are, if it's the adapter that's causing the problem when I run the Remove() method, I would think that code would take me back into my QATB region adapter to where I would see the exception.  However, code isn't making it there.

As I mentioned, the Remove call actually works, there's just something afterwards that having the problem. 

Jun 1, 2011 at 8:05 AM

@kfrasty: I had the exactly the same problem (not with the RibbonBar's QuickAccessToolBar but with my own control), but was eventually able to solve it, apparently I was removing the control twice, once in the target control itself (in OnVisualChildrenChanged) and once in the RegionAdapter ( where the regionTarget is the control in which it was already removed ). So I removed the removal of the visual from the OnVisualChildrenChanged and left the RegionAdapter untouched and now everything works perfectly. I think the removal of the control in OnVisualChildrenChanged was a remnant of the pre prism version of my control where there was no regionAdapter.