RegionCreationException when opening page second time

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

Hello,

I have a Silverlight 4 application with the Prism 4 Library.
In the silverlight application I use the navigation Framework of Silverlight 3 and 4.

Now I have created 2 modules. 1 module is always visible and stays on the side in the Shell page. The other module is visible when I navigate to another page. I use this code in xaml:

<Grid x:Name="LayoutRoot">
        <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
            <StackPanel x:Name="ContentStackPanel">
                
                <ContentControl  x:Name="NavigationItemsControlProduct" regions:RegionManager.RegionName="contentProducts" />
                

            </StackPanel>                
        </ScrollViewer>
    </Grid>

To register the view of the module, I use this code:

[ImportingConstructor]
        public ProductsModule(IRegionManager regionManager)
        {
            if (regionManager == null)
                throw new ArgumentNullException("regionManager");
            
            _regionManager = regionManager;
        }


#region IModule Members

        /// <summary>
        /// initialize the module.
        /// </summary>
        public void Initialize()
        {
            //this._logger.Log("Product module demonstrates logging during Initialize().", Category.Info, Priority.Medium);
            this._regionManager.RegisterViewWithRegion("contentProducts", typeof(Iodine.Products.Views.ProductsView));
        }

        #endregion

The initialize is fired when I start the application. Now if i navigate to the page, the list of products is visible. Everything works fine then.

Now if I navigate back to the home page and after that back to the page where the module is, I get the "RegionCreationException" specified below.

An exception occurred while creating a region with name 'contentProducts'. The exception was: System.ArgumentException: Value does not fall within the expected range.   bij MS.Internal.XcpImports.CheckHResult(UInt32 hr)   bij MS.Internal.XcpImports.SetValue(IManagedPeerBase obj, DependencyProperty property, DependencyObject doh)   bij MS.Internal.XcpImports.SetValue(IManagedPeerBase doh, DependencyProperty property, Object obj)   bij System.Windows.DependencyObject.SetObjectValueToCore(DependencyProperty dp, Object value)   bij System.Windows.DependencyObject.SetEffectiveValue(DependencyProperty property, EffectiveValueEntry& newEntry, Object newValue)   bij System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)   bij System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet)   bij Microsoft.Practices.Prism.Regions.ContentControlRegionAdapter.<>c__DisplayClass2.<Adapt>b__0(Object , NotifyCollectionChangedEventArgs )   bij Microsoft.Practices.Prism.Regions.ViewsCollection.OnCollectionChanged(NotifyCollectionChangedEventArgs e)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.NotifyAdd(IList items, Int32 newStartingIndex)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.NotifyAdd(Object item)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.OnItemMetadataChanged(Object sender, EventArgs e)   bij System.EventHandler.Invoke(Object sender, EventArgs e)   bij Microsoft.Practices.Prism.Regions.ItemMetadata.InvokeMetadataChanged()   bij Microsoft.Practices.Prism.Regions.ItemMetadata.DependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)   bij System.Windows.DependencyObject.RaisePropertyChangeNotifications(DependencyProperty dp, Object oldValue, Object newValue)   bij System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)   bij System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet)   bij Microsoft.Practices.Prism.Regions.Region.Activate(Object view)   bij Microsoft.Practices.Prism.Regions.SingleActiveRegion.Activate(Object view)   bij Microsoft.Practices.Prism.Regions.ContentControlRegionAdapter.<>c__DisplayClass2.<Adapt>b__1(Object sender, NotifyCollectionChangedEventArgs e)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.OnCollectionChanged(NotifyCollectionChangedEventArgs e)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.NotifyAdd(IList items, Int32 newStartingIndex)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.NotifyAdd(Object item)   bij Microsoft.Practices.Prism.Regions.ViewsCollection.SourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)   bij System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)   bij System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)   bij System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)   bij System.Collections.ObjectModel.Collection`1.Add(T item)   bij Microsoft.Practices.Prism.Regions.Region.InnerAdd(Object view, String viewName, IRegionManager scopedRegionManager)   bij Microsoft.Practices.Prism.Regions.Region.Add(Object view, String viewName, Boolean createRegionManagerScope)   bij Microsoft.Practices.Prism.Regions.Region.Add(Object view)   bij Microsoft.Practices.Prism.Regions.Behaviors.AutoPopulateRegionBehavior.AddViewIntoRegion(Object viewToAdd)   bij Microsoft.Practices.Prism.Regions.Behaviors.AutoPopulateRegionBehavior.StartPopulatingContent()   bij Microsoft.Practices.Prism.Regions.Behaviors.AutoPopulateRegionBehavior.OnAttach()   bij Microsoft.Practices.Prism.Regions.RegionBehavior.Attach()   bij Microsoft.Practices.Prism.Regions.RegionBehaviorCollection.Add(String key, IRegionBehavior regionBehavior)   bij Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.AttachDefaultBehaviors(IRegion region, T regionTarget)   bij Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Initialize(T regionTarget, String regionName)   bij Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Microsoft.Practices.Prism.Regions.IRegionAdapter.Initialize(Object regionTarget, String regionName)   bij Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName). 
   bij Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName)   bij Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.TryCreateRegion()   bij Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.ElementLoaded(Object sender, RoutedEventArgs e)   bij MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)   bij MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

I can reproduce this everytime. It looks like the view is registered twice???

Has anybody any suggestions?

Developer
Jan 4, 2011 at 4:36 PM

Hi,

You might find this blog post by Karl Shifflett useful, as it deals with the integration of the Silverlight Navigation Framework with Prism Region Navigation. Switching to the approach explained in the blog post might address your issue.

If you keep experiencing problems around this, it could be useful if you could provide us with a repro sample, so that we can help you solve it.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Jan 5, 2011 at 4:56 PM

You could probably get around this by setting the RegionMemberLifetime to false on the view your adding to the region.

Something like this

[RegionMemberLifetime(KeepAlive = false)]
public partial class ProductsView
{
}

So when you move to some other view regionManager will deactive this view and remove it. So next time you get to that view you would be fine. 

Jan 19, 2011 at 9:31 AM

Hi GuidoMaliandi,

Thanks for the fast response and sorry for the late response. I had some troubles with implementing the blogpost because we also using downloading dynamic xap files. I also forgot to implement ConfigureRegionAdapterMappings in the bootstrapper. My application was working but when I started the application I was getting an error that a frame could not be converted to an usercontrol. After I had set the bootstrapper correctly, everything was working fine!

@gan s: Thx for the response but it didn't worked for me. I still had the same problem. 

Feb 9, 2011 at 5:53 PM

Hello LockTar,

When you inspect the Views Collection of your Region you will see that your Iodine.Products.Views.ProductsView will remain in the collection.
If you go back to your page (activate it for the second time) the view will be added again to the Collection. Then the RegionCreationException will occur.
To prevent this add the  [PartCreationPolicy(CreationPolicy.NonShared)]  attribute to your View. This will destroy and recreated a new view each time you request the page.

By the way this problem only occurs when you are using the MefBootstrapper. Don't ask me why... (If someone knows please tell me :-) )

Feb 10, 2011 at 9:29 AM

Hello AHorNet,

Thanks for your response! I was already playing with the [PartCreationPolicy(CreationPolicy.NonShared)] attribute above the IModule implementation but that was not working. Setting it above the View that is placed with the code below did the trick.

this._regionManager.RegisterViewWithRegion("contentProducts", typeof(Iodine.Products.Views.ProductsView));

Thank you for the solution! The only thing that I see now, is that the memory is increasing each time you visit the page. I have to figure out how that comes.

P.S. I already did a test with Unity. It was very frustrating to see that Unity was working and MEF not. But now it's fixed :-)

May 3, 2011 at 2:39 AM
Edited May 23, 2011 at 9:28 PM
LockTar wrote:

Hello AHorNet,

Thanks for your response! I was already playing with the [PartCreationPolicy(CreationPolicy.NonShared)] attribute above the IModule implementation but that was not working. Setting it above the View that is placed with the code below did the trick.

 

 

Thank you for the solution! The only thing that I see now, is that the memory is increasing each time you visit the page. I have to figure out how that comes.

P.S. I already did a test with Unity. It was very frustrating to see that Unity was working and MEF not. But now it's fixed :-)

 

this._regionManager.RegisterViewWithRegion("contentProducts", typeof(Iodine.Products.Views.ProductsView));

What fixed? MefBootstrapper? If not than when it be fixed???

May 6, 2011 at 1:38 PM

I fixed the problem that I could not open the page for the second time. 
Can you explain your question? I don't really understand it. 

May 6, 2011 at 10:43 PM

Ok, I try to explain my problem, despite my english is poor.

I need only one instance of my view in project. That's why  I'm apply attribute:

[PartCreationPolicy(CreationPolicy.NonShared)]

Method intended for switch views in region:

private void MainRegionSwitch(string viewName)
{
	string main = string.Concat(viewName, "Main");
	IRegion regionMain = this.RegionManager.Regions[RegionNames.MainRegion];
	object viewMain = regionMain.GetView(main);
	if (viewMain == null)
	{
		viewMain = ServiceLocator.Current.GetInstance(GetTypeMainView(viewName));
		this.RegionManager.Regions[RegionNames.MainRegion].Add(viewMain, main);
	}
	regionMain.Activate(viewMain);
}

When I run my application everything working. And then I'm using ServiceLocator getting instance of my view in another ViewModel:

object maps = ServiceLocator.Current.GetInstance<IMapsView>();

It's working until I try to switch previous instance view. I getting error: "Value does not fall within the specified range". You can see at the screenshots.

1 Two instances in my app (View 1) from different modules.

2 Two instances in my app (View 2) from different modules.

3 Two instances in another view, where they are was got by ServiceLocator and put they to the third view (master-detail approach)

4 try to switch previous view of instance

5 Error!!!

May 23, 2011 at 2:14 PM

Calabonga,

Sorry for the very late response!

The error that you are getting. It says that it doesn't exist. But when you debug it, can you see the page in debug mode? I mean, do you see the item in the list of views?

Are you using the MVVM pattern? Where did you add the PartCreationPolicy? 

May 23, 2011 at 9:27 PM
LockTar wrote:

The error that you are getting. It says that it doesn't exist. But when you debug it, can you see the page in debug mode? I mean, do you see the item in the list of views?

Are you using the MVVM pattern? Where did you add the PartCreationPolicy? 

I found that error not in PRISM. Error is in Silverlight core.
Error appear in method:

		#region INotifyPropertyChanged Members
		public event PropertyChangedEventHandler PropertyChanged;

		private void NotifyPropertyChanged(string propertyName)
		{
			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); // <-- Error appeared here
			}
		}
		#endregion

I don't understand why it happening. I was exclude all features PRISM and MEF, but error not disappear. I can send you my test solution and explain how you can get error.