Changing theme at runtime - RadPaneGroupRegionAdapter crash.

7 posts, 0 answers
  1. Craig Dean
    Craig Dean avatar
    16 posts
    Member since:
    Jan 2010

    Posted 01 Feb 2010 Link to this post

    Hi,

    I have previously been changing ApplicationTheme at runtime, successfully, by re-adding my main control.  This causes a number of problems.  Recently I started getting a strange scenario.

    My MainView defines Prism Regions, removing it and re-adding it causes those regions to be removed and readded.  I also have a docking control and am using the RadPaneGroupRegionAdapter as suggested in your blogs.

    As I re-add the main view, (with it's associated regions), the region manager correctly starts re-adding the child views.  The Adapt method is called in RadPaneGroupRegionAdapter  (as expected) to re-add the associated RadPanes.

    The Views.CollectionChanged event fires, calling the lambda expression with an Action of NotifyCollectionChangedAction.Add, to re-add the old views - again as expected.

    The problem is these views were previously associated with a docking control from the old control that is no longer present, therefore their parent is not null.  Calling regionTarget.Items.Add(item) therfore crashes as the item already belongs to another collection.

    The solution appears to be -
                                                                     
    if (item.Parent != null)  
       item.RemoveFromParent();  
    regionTarget.Items.Add(item);

    Unfortunately, the RemoveFromParent throws an exception:
    {System.Exception: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
    at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
    at MS.Internal.XcpImports.FrameworkElement_SetStyleValue(FrameworkElement dohDependencyProperty propertyPropertyInvalidationReason reason)
    at System.Windows.DependencyObject.ClearValueInternal(DependencyProperty dp)
    at System.Windows.DependencyObject.ClearValue(DependencyProperty dp)
    at Telerik.Windows.Controls.RadPaneGroup.RemovePane(RadPane pane)
    at Telerik.Windows.Controls.RadPane.RemoveFromParent()
    at WebApplications.Siverlight.PrismExtensions.Regions.RadPaneGroupRegionAdapter.<>c__DisplayClass2.<Adapt>b__0(Object sNotifyCollectionChangedEventArgs e)
    at Microsoft.Practices.Composite.Presentation.Regions.ViewsCollection.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    at Microsoft.Practices.Composite.Presentation.Regions.ViewsCollection.AddAndNotify(IList items)
    at Microsoft.Practices.Composite.Presentation.Regions.ViewsCollection.UnderlyingCollection_CollectionChanged(Object senderNotifyCollectionChangedEventArgs e)
    at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 indexT item)
    at System.Collections.ObjectModel.Collection`1.Add(T item)
    at Microsoft.Practices.Composite.Presentation.Regions.Region.InnerAdd(Object viewString viewNameIRegionManager scopedRegionManager)
    at Microsoft.Practices.Composite.Presentation.Regions.Region.Add(Object viewString viewNameBoolean createRegionManagerScope)
    at Microsoft.Practices.Composite.Presentation.Regions.Region.Add(Object view)
    at Microsoft.Practices.Composite.Presentation.Regions.Behaviors.AutoPopulateRegionBehavior.AddViewIntoRegion(Object viewToAdd)
    at Microsoft.Practices.Composite.Presentation.Regions.Behaviors.AutoPopulateRegionBehavior.StartPopulatingContent()
    at Microsoft.Practices.Composite.Presentation.Regions.Behaviors.AutoPopulateRegionBehavior.OnAttach()
    at Microsoft.Practices.Composite.Presentation.Regions.RegionBehavior.Attach()
    at Microsoft.Practices.Composite.Presentation.Regions.RegionBehaviorCollection.Add(String keyIRegionBehavior regionBehavior)
    at Microsoft.Practices.Composite.Presentation.Regions.RegionAdapterBase`1.AttachDefaultBehaviors(IRegion regionT regionTarget)
    at Microsoft.Practices.Composite.Presentation.Regions.RegionAdapterBase`1.Initialize(T regionTargetString regionName)
    at Microsoft.Practices.Composite.Presentation.Regions.RegionAdapterBase`1.Microsoft.Practices.Composite.Regions.IRegionAdapter.Initialize(Object regionTargetString regionName)
    at Microsoft.Practices.Composite.Presentation.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElementString regionName)}

    Possibly because the parent is unloaded?  It doesn't set the items parent to null first either, so even if you catch the error, the corresponding Add still fails.  Obviously the problem seems to be that under certain scenarios Prism doesn't tell the adapter about region removals.  However, it is only the adapter that fails under those scenarios, suggesting that there is a slight design issue - an assumption is being made that you are always told when views are removed from a region?

    Thanks
  2. Craig Dean
    Craig Dean avatar
    16 posts
    Member since:
    Jan 2010

    Posted 01 Feb 2010 Link to this post

    OK, tried to add the following before removing the regions, as a workaround -

    foreach (RadPane rpg in 
        _regionManager.Regions.SelectMany(  
            region =>  
            region.Views.Select(view => view as RadPane).Where(rpg => (rpg != null) && (rpg.Parent != null)))  
        )  
        rpg.RemoveFromParent(); 

    This looks for all RadPane views in the region manager (that have a parent), and calls remove from parent on them.  Unfortunately get this error-

    {System.Exception: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
    at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
    at MS.Internal.XcpImports.FrameworkElement_SetStyleValue(FrameworkElement dohDependencyProperty propertyPropertyInvalidationReason reason)
    at System.Windows.DependencyObject.ClearValueInternal(DependencyProperty dp)
    at System.Windows.DependencyObject.ClearValue(DependencyProperty dp)
    at Telerik.Windows.Controls.RadPaneGroup.RemovePane(RadPane pane)
    at Telerik.Windows.Controls.RadPane.RemoveFromParent()
    at WebApplications.Siverlight.BabelAdmin.MainView.MainViewModule.themeChanged(IBabelAdminTheme babelAdminTheme)}

    * UPDATE *
    The above error is caused as I had already changed the ApplicationTheme at this point - removing a RadPane from it's parent when the ApplicationTheme is changed causes the exception.
  3. DevCraft banner
  4. Miroslav Nedyalkov
    Admin
    Miroslav Nedyalkov avatar
    1718 posts

    Posted 05 Feb 2010 Link to this post

    Hello Craig,

     First of all I want to apologize for the late response.

    Is this error still exist if you remove the panes before changing the theme? If yes, could you please open a support ticket and send a sample project that reproduces the problem - this will let us investigate what the problem is.

    Regards,
    Miroslav Nedyalkov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  5. Craig Dean
    Craig Dean avatar
    16 posts
    Member since:
    Jan 2010

    Posted 05 Feb 2010 Link to this post

    Yes, the first error does continue to occur regardless of the theme change.  It boils down to how Prism regions appear to work, and especially if you re-use instances of objects rather than discarding and putting back together.

    The project I have is not disimilar to SQL Management Studio or Visual Studio in size and layout (i.e. massive), and as such is impossible to send.  It would take me quite some time to produce a sample solution that reproduces the problem exactly.  For now I have disabled theme switching on the application (you can change theme but it will only take effect on next reboot.  Silverlight has proven something of a nightmare developmenet experience as it is fiendishly difficult to debug XAML problems, so we're still undecided as to whether we will move our project out of it's current feasibility study into production.

    I will be revisiting this particular issue when I look at improving the Dock Save/Load layout functionality (It currently depends on all the saved component being available on load - which is rarely true in a Prism scenario - instead I will be looking to modify layout loading to instead remember where components should be loaded at the point they are eventually added).

    Thanks.
  6. Miroslav Nedyalkov
    Admin
    Miroslav Nedyalkov avatar
    1718 posts

    Posted 05 Feb 2010 Link to this post

    Hi Craig,

     In Silverlight 4 you will not need to reload your controls when you switch between themes, so this problem will not exist anymore.

    About the Load layout - you are correct, but the default behavior is implemented just for simple scenarios where you have some components declared in XAML and this assumption that the all needed components are available on load, is true.

    Unfortunately it is very hard to handle complex scenarios for saving/loading the layout. For these complex scenarios we provided an infrastructure that will let you hook-up to events and load the views that should be loaded when the layout is loading. You could us the events of the Docking control that start with Element - they are all connected to the Load layout feature.

    You could also use the CurrentSaveLoadLayoutHelper property of the Docking control that is of type SaveLoadLayoutHelper. You could inherit from this class and implement you logic in its overrides - the default one finds the already loaded panes and maps them to the layout that should be loaded.

    Hope this information is helpful.

    Kind regards,
    Miroslav Nedyalkov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  7. Phillip Hamlyn
    Phillip Hamlyn avatar
    26 posts
    Member since:
    Jul 2009

    Posted 21 May 2010 Link to this post

    Miroslav,

    We are currently developing on Silverlight 4 using your control pack for Silverlight. I would like to change the Application Theme at runtime based on a user selection. You mention in the previous post that this is now possible in Silverlight 4 without unloading and reloading the control stack. Could you tell me how this can be achieved please ?

    Phillip
  8. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 28 May 2010 Link to this post

    Hi Phillip Hamlyn,

    I'm sorry for the late response. Unfortunately we didn't manage to implement this change is our theming mechanism so this is still not possible.

    I'm sorry for the inconvenience caused.

    All the best,
    Hristo
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Back to Top
DevCraft banner