Cancel Region.Remove(view)

Topics: Prism v4 - WPF 4
Feb 2, 2012 at 11:27 PM

I'm looking for the "best practice" approach to providing something like the INavigationAware interface but without using the navigation methods to switch views.

Using Prism/MEF v4.

I inject views without problem.  I can remove views without problem.

I remove views by something outside the target view (usually in my controller) will get a handle to the view and call Region.Remove(view).  Something like this:



(The insert code snippet control does not work for me in Chrome or IE so please forgive the formatting)

... some method

      IRegion region = scopedRegion.Regions[RegionNames.SomeRegion];
      var previousView = region.Views.First(reg => reg.GetType().Equals(typeof(SomeView)));
      region.Remove(previousView);     


 

I'm looking for a way to have each view check if it is allowed to be removed.

If not, cancel the call to Remove (such as when the view has pending changes that need to be saved)

Ideally there is some way to use the INavigationAware implementation but without using RequestNavigate(Uri...) to change views since I'm NOT using that navigation pattern.

I can easily control whether or not to allow my view to initiate being closed (such as on a cancel button click etc) since I'm in scope to check IsDirty() methods etc.

What I can't do is have parent views try to remove a child view, where the child view blocks the removal.

About the closest thing I've found was this article:
http://blogs.msdn.com/b/dphill/archive/2011/01/23/closable-tabbed-views-in-prism.aspx

There he's using the INavigationAware methods with Blend triggers.  I use that approach when my parent tabs close, but I need something similar for nested views inside my UI structure. 


Developer
Feb 3, 2012 at 6:06 PM

Hi,

Based on my understanding, the implementation details of the features you are describing will depend mostly of your personal preferences and the requirement of your scenario.

A possible approach could be to create an extension method that checks if the view should be removed or not before removing it.

As an example, you could implement an interface that exposes an IsDirty property in each view that you want to be able to cancel its removal. Then, instead of using the Remove method to remove the views, you could use an extension method that checks this property, and if it returns false, the view is removed:

    public static class RegionExtensions
    {
        // Returns true if the view was removed and false otherwise.
        public static bool RemoveIfNotDirty(this IRegion region, object view)
        {
            // IConfirmRemove is a custom interface that exposes an IsDirty property...
            IConfirmRemove confirmableView = view as IConfirmRemove; 
            if (confirmableView != null)
            {
                if (confirmableView.IsDirty == false)
                {
                    // If the view is not dirty, we can remove it.
                    region.Remove(view);
                    return true;
                }
                else
                {
                    // If the view IS dirty, the view is not removed.
                    return false;
                }
            }
            else
            {
                // If the region does not implement IConfirmRemove, we simply remove it like a common view.
                region.Remove(view);
                return true;
            }
        }
    }

Like this, parent views / view models can be abstracted from the logic to check if the view should be removed or not. Also, you could improved this approach to include any other required functionality, like invoking callbacks, raising events, etc.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Feb 14, 2012 at 3:41 PM

Thanks for the reply, Damian.  That looks like a solid direction to go in and I'll get to implementing something soon, I just got sidetracked on other things in the meantime.

Cheers