What would be the best practice to remove a view from a region?

Topics: Prism v4 - WPF 4
Mar 18, 2013 at 9:17 PM
I'm really new to Prism and trying to understand the proper way to remove a view from a region. I have written a simple WPF MVVM Prism application that has one region (MainRegion) with two buttons (Button A and Button B) in Shell view.

Basically when clicking the Button A it will navigate to ViewA. The same way for the Button B, it will navigate to ViewB when it's clicked. These two views are populated in MainRegion. Here is what I register them in IUnityContainer in Initialize():
Public Class MainModule
    Implements IModule

    Private ReadOnly _container As IUnityContainer

    Public Sub New(container As IUnityContainer)
        Me._container = container
    End Sub

    Public Sub Initialize() Implements Microsoft.Practices.Prism.Modularity.IModule.Initialize
        _container.RegisterType(Of Object, View)("ViewA")
        _container.RegisterType(Of Object, View)("ViewB")

    End Sub
End Class

Here are codes when clicking Button A and Button B
    Sub ButtonACommandClicked()
        RemoveViews() 'To review all views before navigating
        Dim regionManager = ServiceLocator.Current.GetInstance(Of IRegionManager)()

        Dim listUri = New Uri("ViewA", UriKind.Relative)
        regionManager.RequestNavigate("MainRegion", listUri, AddressOf NavigationToViewA)
    End Sub

    Sub ButtonBCommandClicked()
        RemoveViews() 'To review all views before navigating
        Dim regionManager = ServiceLocator.Current.GetInstance(Of IRegionManager)()

        Dim listUri = New Uri("ViewB", UriKind.Relative)
        regionManager.RequestNavigate("MainRegion", listUri, AddressOf NavigationToViewB)
    End Sub

    Private Sub RemoveViews()
        Dim regionManager = ServiceLocator.Current.GetInstance(Of IRegionManager)()
        Dim views = regionManager.Regions("MainRegion").Views

        For Each view In views
    End Sub
Is this the right way to remove the view? If I don't call RemoveView(), the new view that is being navigated will be appended to the existing view loaded before.

Please advise.

Mar 19, 2013 at 5:55 PM

As far as I know, there are two possible ways to remove a view from your Region, both of which are correct:
  • Use the Remove method on a Region passing the view you want to remove as a parameter (as you are already doing)
  • Make your views implement IRegionMemberLifetime and change the KeepAlive property to return false. This way, next time you want to remove a view, you could call the Deactivate method instead, so your view will be first deactivated and then, since KeepAlive is set to return false, removed.
Nevertheless, taking into account the context of your application, the commonly used method is to implement IRegionMemberLifetime on your Views/ViewModels. Basically, when you navigate to a view, the previous activated view will be automatically deactivated and therefore removed thanks to the IRegionMemberLifetime, without the need to do it manually.

You could find more information about this in the following section of the Prism documentation:
Hope this helps,

Federico Martinez
Mar 28, 2013 at 4:03 AM
Hi fmartinez,

I implemented IRegionMemberLifttime in views and set the breakpoint, but the KeepAlive property did not get called. Any idea?

Mar 29, 2013 at 11:52 AM
Finally I got it working with some confusions. The problem why the KeepAlive property did not get called was because I used ItemControl as the region container. Then I changed to use ContenControl. The KeepAlive property got called and the view got removed when navigating. However, since the ContentControl is being used for the region container, I'm curious that if none of views (or view models) implement IRegionMemberLifetime, would removing a view still work? The result is that it's still working without IRegionMemberLifetime.
      - Is this the prism behavior by default?
      - What controls for the region container are applicable to the KeepAlive property? For my experiences, ItemControl does not work. Only ContentControl works.
Apr 3, 2013 at 7:40 PM
Hi Brew,

Basically, Prism's Regions work differently depending on the control they are being adapted to. In this particular case, we have two different regions types: the SingleActiveRegion (for ContentControls) and the AllActiveRegion (for ItemsControls).

When you where using an ItemsControl, you had an AllActiveRegion, which basically is a region that never deactivates its views, and therefore, all its views will be considered active. In such scenario, the IRegionMemberLifetime will not work, as it's only used when a view in the region is deactivated (which never happens in an AllActiveRegion).

Then, when you changed to a ContentControl, you had a SingleActiveRegion, which is a region that only allows one view to be active at the same time; all the rest of the views in the control are deactivated. In this case, the "visible" view in the control will be the active one, meaning the deactivated views will not be shown (but will be stored inside the region instance). In this scenario, the IRegionMemberLifetime is used when a view is injected or activated as the previous one will be automatically deactivated.

Take into account that the default behavior in Prism for views / view models that do not implement the IRegionMemberLifetime interface or attribute is to keep the view alive (as if they had the KeepAlive property set to true). Hence, in a ContentControl, when injecting such a view, the previous view will not be visible but will be kept alive in the region, consuming resources. If those views / view models had the KeepAlive property set to false, they would not only be removed from the control but also from the region completely upon deactivation.

I hope this helps,

Damian Cherubini
Apr 4, 2013 at 3:17 AM
Hi Damian,
This is really helpful and makes me more understanding about prism.

Thank you for both of you (Damian and Federico)!