Hide/Show views in regions

The IRegion interface allows to Add/Remove and activate/deactivate it's views. One behavior that is not implemented out-of-the-box in prism-v2 is the possibility of hiding views while keeping the view in the region.

Hiding view only makes sense in ItemsControl containers, as in other containers views are automatically hidden when they are not active. Hiding views might be particularly helpful, for example if there is a requirement to hide certain TabItems (as deactivating the view won't hide the tab, and hiding the view won't hide the tab).

The following two classes (one for Silverlight and one for WPF) add extension methods to allow hide/show views in prism-v2 regions. WPF methods implement hide/show for all ItemsControl containers while Silverlight methods are only implemented for the TabControl:
  • SilverlightRegionExtensions (allow hide views in TabControl regions)
  • WPFRegionExtensions (allow hide views in ItemsControl regions)

The aforementioned classes expose the following extension methods for the IRegion interface:
  • Hide(string viewName): Hides a view registered with a particular name in the region.
  • Hide(object view): Hides the view passed as a parameter.
  • Show(string viewName): Shows a view registered with a particular name in the region.
  • Show(object view): Shows the view passed as a parameter.

You can download the source code for the classes below from here: RegionExtensions.zip.

Disclaimer

This code is provided “AS IS” with no warranties, and confers no rights.

WPFRegionExtensions.cs

public static class RegionExtensions
{
    public static void Hide(this IRegion region, string viewName)
    {
        Hide(region, region.GetView(viewName));
    }
   
    public static void Show(this IRegion region, string viewName)
    {
        Show(region, region.GetView(viewName));
    }


    public static void Show(this IRegion region, object view)
    {
        ChangeViewVisibility(region, view, Visibility.Visible);
    }

    public static void Hide(this IRegion region, object view)
    {
        ChangeViewVisibility(region, view, Visibility.Collapsed);
    }

    private static void ChangeViewVisibility(IRegion region, object view, Visibility visibility)
    {
        // Validate that the region is attached to an ItemsControl
        ItemsControl attachedControl = GetAttachedControl(region) as ItemsControl;
        if (attachedControl == null)
            throw new ArgumentException("The region must be attached to an ItemsControl");

        // Validate that the view is inside the region
        if(!region.Views.Contains(view))
            throw new ArgumentException("The view is not in the region");

        // Get the ItemContainer 
        UIElement viewContainer = attachedControl.ItemContainerGenerator.ContainerFromItem(view) as UIElement;
        if (viewContainer != null)
        {
            // show / hide the ItemContainer
            viewContainer.Visibility = visibility;

            // show/ hide the view
            UIElement viewElement = view as UIElement;
            viewElement.Visibility = visibility;

            // activate other view if necessary 
            Selector selector = attachedControl as Selector;
            if(selector != null && visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
            {
                // if there is another view that can be shown
                var viewToActivate = NextViewToActivate(region, view);

                if (viewToActivate != null)
                {
                        region.Activate(viewToActivate);
                }
            }
            // Uncomment the following lines to activate a view when you show it again
            /*else if(selector != null)
            {
                Activate the view
                region.Activate(view);   // It is not always needed activate the view when unhiding
            }*/
        }
    }

    private static object NextViewToActivate(IRegion region, object view)
    {
        var currentActiveView = region.ActiveViews.FirstOrDefault();
        // if the view to hide is the active view and there are other visible views
        if ((currentActiveView == null || view == currentActiveView) && region.Views.Any(v => v != view && (v as UIElement).Visibility == Visibility.Visible))
        {
            return region.Views.First(v => v != view && (v as UIElement).Visibility == Visibility.Visible);
        }
        return null;
    }

    public static DependencyObject GetAttachedControl(this IRegion region)
    {
        RegionManagerRegistrationBehavior behavior = (RegionManagerRegistrationBehavior)region.Behaviors.First(b => b.Key == RegionManagerRegistrationBehavior.BehaviorKey).Value;
        return behavior.HostControl;
    }
}

SilverlightRegionExtensions.cs

public static class RegionExtensions
{
    public static void Hide(this IRegion region, string viewName)
    {
        Hide(region, region.GetView(viewName));
    }

    public static void Show(this IRegion region, string viewName)
    {
        Show(region, region.GetView(viewName));
    }


    public static void Show(this IRegion region, object view)
    {
        ChangeViewVisibility(region, view, Visibility.Visible);
    }

    public static void Hide(this IRegion region, object view)
    {
        ChangeViewVisibility(region, view, Visibility.Collapsed);
    }

    private static void ChangeViewVisibility(IRegion region, object view, Visibility visibility)
    {
        // Validate that the region is attached to an TabControl
        TabControl attachedControl = GetAttachedControl(region) as TabControl;
        if (attachedControl == null)
            throw new ArgumentException("The region must be attached to an TabControl");

        // Validate that the view is inside the region
        if (!region.Views.Contains(view))
            throw new ArgumentException("The view is not in the region");

        // Get the ItemContainer 
        TabItem tabItem = GetViewTabItem(view as FrameworkElement);
        /*if (tabItem != null)
        {*/
            // show / hide the ItemContainer
            tabItem.Visibility = visibility;

            // show/ hide the view
            UIElement viewElement = view as UIElement;
            viewElement.Visibility = visibility;

            // activate other view if necessary 
            if (visibility == Visibility.Collapsed)
            {
                // if there is another view that can be shown
                var viewToActivate = NextViewToActivate(region, view);

                if (viewToActivate != null)
                {
                    region.Activate(viewToActivate);
                }
            }
            // Uncomment the following lines to activate a view when you show it again
            /*else if(selector != null)
            {
                Activate the view
                region.Activate(view);   // It is not always needed activate the view when unhiding
            }*/
       // }
    }

    private static TabItem GetViewTabItem(FrameworkElement element)
    {
        TabItem item = element as TabItem;
        if (item != null)
        {
            return item;
        }
        return GetViewTabItem(element.Parent as FrameworkElement);
    }

    private static object NextViewToActivate(IRegion region, object view)
    {
        var currentActiveView = region.ActiveViews.FirstOrDefault();
        // if the view to hide is the active view and there are other visible views
        if ((currentActiveView == null || view == currentActiveView) && region.Views.Any(v => v != view && (v as UIElement).Visibility == Visibility.Visible))
        {
            return region.Views.First(v => v != view && (v as UIElement).Visibility == Visibility.Visible);
        }
        return null;
    }

    public static DependencyObject GetAttachedControl(this IRegion region)
    {
        RegionManagerRegistrationBehavior behavior = (RegionManagerRegistrationBehavior)region.Behaviors.First(b => b.Key == RegionManagerRegistrationBehavior.BehaviorKey).Value;
        return behavior.HostControl;
    }
}

Last edited Jul 1, 2009 at 4:06 PM by dschenkelman, version 3

Comments

No comments yet.