First time at my blog? Check out the table of contents! x
posted on Tuesday, May 05, 2009 7:51 PM | Filed Under [ DotNetNuke Open Source ]

So how do you elegantly manage the different views or “pages” in your DotNetNuke module? This has to be one of the most frequently asked questions I see regarding DotNetNuke module development. Since module instances live on pages, possibly with instances of other modules, it can be tricky to switch between the pages (aka the “views”) within your module, while at the same time leaving the rest of the DotNetNuke page unchanged.

In the recently published book Professional DotNetNuke Programming by Mitchel Sellers, the author outlines the basics of several ways you can manage the views in your module. One of the methods he mentions involves using a MuiltiView control. This is the method I am going to demonstrate today. I am also going to share with you a helper class that I wrote that will allow you to more elegantly separate your views into UserControls that have all the same functionality of your standard PortalModuleBase control.

Let’s begin.

 

The Main View

When you are using the MultiView method to manage the views of your module, your module definition contains one main view that under most circumstances will not be navigated away from. In this example I simply named this control View.ascx.

image

If you aren’t familiar with the ASP.Net MultiView, the basic idea is that it allows you to show or hide a grouping of other controls and web content. Inside the single instance of a MultiView you declare several instance of the ASP.Net View control, each with an id. You tell the MultiView which View it should display, and only that View will be rendered and sent out to the browser.

In order to keep our module code clean, we will separate the code for each of our views into different UserControls. An instance of each control will then be placed inside its own ASP.Net View control inside the MultiView.

<asp:MultiView ID="MultiView1" runat="server">
    <asp:View ID="HomveView" runat="server">
        <h4>
            This is the home view</h4>
    </asp:View>
    <asp:View ID="View1" runat="server">
        <ke:Control1 ID="control1" runat="server">
        </ke:Control1>
    </asp:View>
    <asp:View ID="View2" runat="server">
        <ke:Control2 ID="control2" runat="server">
        </ke:Control2>
    </asp:View>
    <asp:View ID="View3" runat="server">
        <ke:Control3 ID="control3" runat="server">
        </ke:Control3>
    </asp:View>
</asp:MultiView>

Here we have 3 views inside our MultiView, one View control for each of our custom UserControls (Control1, Control2, and Control3).

 

Navigating Between The Views

Navigating between the views contained in the MultiView is as easy calling the SetActiveView on the MultiView, passing to it the view that you want to show. In the code-behind for the main View.ascx file of our module, we’ll read a query string parameter called ModuleView in order to determine which view to display.

switch (Request.Params["ModuleView"])
{
    case "view1":
        MultiView1.SetActiveView(View1);
        break;
    case "view2":
        MultiView1.SetActiveView(View2);
        break;
    case "view3":
        MultiView1.SetActiveView(View3);
        break;
    default:
        MultiView1.SetActiveView(HomveView);
        break;
}

Now that we have this functionality built into our module, you can manually switch between the views of the module by passing a parameter in the query string. Of course we can’t expect a user to do this, so we have to build some sort of navigation between the views of our module. We’ll create another control for this purpose that has 3 hyperlinks. Each hyperlink will link to the current page, passing the ModuleView parameter that corresponds to the view that the link should take the user to.

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="ViewNavigation.ascx.cs"
    Inherits="Kemmis.Modules.ViewManagement.ViewNavigation" %>
<asp:HyperLink ID="HyperLink1" runat="server">
    Show View 1</asp:HyperLink>
<br />
<asp:HyperLink ID="HyperLink2" runat="server">
    Show View 2</asp:HyperLink>
<br />
<asp:HyperLink ID="HyperLink3" runat="server">
    Show View 3</asp:HyperLink>
<br />

Here we set the hyperlink navigateurl in the code-behind:

HyperLink1.NavigateUrl = 
    Globals.NavigateURL(TabId, "", "ModuleView=view1");
HyperLink2.NavigateUrl = 
    Globals.NavigateURL(TabId, "", "ModuleView=view2");
HyperLink3.NavigateUrl = 
    Globals.NavigateURL(TabId, "", "ModuleView=view3");

 

One Gotcha With A Solution

If you’re following along and you just tried to compile your module, you probably noticed a small problem. Our navigation control is an ordinary UserControl, so it doesn’t have direct access to DotNetNuke specific entities like TabID and the DNN Globals object. No worries, there’s an easy solution.

In order to give sub-controls in my modules access to all the functionality that the main module controls have, I’ve essentially made my sub-controls inherit from PortalModuleBase. However because of the way the DotNetNuke framework functions, sub-controls that inherit from PortalModuleBase do not get configured properly the way that main module controls do. You have to do this configuration in your own code. But don’t worry; I’ve done the work for you. You just need to inherit from the class I’m providing you called PortalModuleChild. This class inherits from PortalModuleBase and configures itself so that it can access the normal DotNetNuke integration points that main module controls have access to.

Here it is:

using System;
using System.Collections.Generic;
using System.Web;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Common;

namespace Kemmis.DNN
{
    public class PortalModuleChild :PortalModuleBase
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            System.Web.UI.Control parent = Parent as System.Web.UI.Control;
            while (!(parent is PortalModuleBase))
            {
                parent = parent.Parent;
            }
            ModuleConfiguration = ((PortalModuleBase)parent).ModuleConfiguration;
        }

        protected String CurrentView
        {
            get
            {
                return Request.Params["ModuleView"];
            }
        }

        protected string getEntityLink(int entityID)
        {
            return Globals.NavigateURL(TabId, "", 
                "ModuleView=EntityDetails&EntityID=" + entityID);
        }
    }
}

 

A Few More Things

One thing to keep in mind when working with the MultiView and View controls is that even though a View might not be the active View for the MultiView, its code is still executed normally inside the ASP.Net page life-cycle. This means that even though a View might not be visible, a control inside the View will still be doing things like querying the database or talking to your business logic layer, unless you explicitly tell it not to. So let’s take care of that problem.

You’ll notice that in my PortalModuleChild class I added a property called CurrentView. This property returns the value of the ModuleView query string parameter. This property can be used to check to see what view your module is in. Once you make your sub-controls inherit from PortalModuleChild, you’ll be able to use this property to determine if the module is in the view for which the sub-controls is required to run its code.

So inside your control, just wrap your code in an if statement like this to determine if the code should be executed:

protected void Page_Load(object sender, EventArgs e)
{
    if (CurrentView == "view1")
    {
        // do view 1 logic only if
        // module is showing this view
    }
}

 

And Another Tip

The PortalModuleChild class is a great place to insert data or functionality that you wish to make available to all of the sub-controls in your module. In my example you’ll see that I added (but didn’t use) a method called getEntityLink. This is a basic example of how you might provide a way for your sub-controls to quickly access the URL to a specific piece of content that your module can display. For example the “Entity” in your module might be a product. You could name your method getProductLink, and have it accept an SKU for the product. It would then return a URL that will allow the module to navigate to the particular view that displays products and accepts an SKU parameter in the query string.

These URL helper methods you can define once in your PortalModuleChild class, and use in any control that inherits from that class. There are plenty of other useful additions you can make to the PortalModuleChild class that I’m sure you can think of on your own. So go crazy!

 

In Summary

So managing the views of your module might not be an out-of-the-box functionality of the DotNetNuke framework, but it can be done quite elegantly using the ASP.Net MultiView control. Remember that all the code in your views will by default be executed, so don’t forget to add conditional statements in your views to check that the module is in the view for which your sub-control needs to execute its code.

And don’t forget to try out the PortalModuleChild class. In just about every module I’ve written I’ve found myself writing the same code over and over in each control. By using the PortalModuleChild class I’ve been able to write that code once, and still access it from within all of my controls.

That’s it! I hope you find this information helpful. You can access the example project code here.

Comments Leave Yours... No comments posted yet.

Post Your Comment

Title
Required
Name
Required
Email
Optional
Url
Optional
Comment  
Please add 7 and 3 and type the answer here:

Who Is Rafe

rafe

Rafe Kemmis

I am an audacious web developer with a double bachelor of science in Computer Science and Mathematics. I specialize in Microsoft ASP.Net, Silverlight, and Adobe ActionScript.

Questions?

Always a thoughtful response. You may post your question on an article, or contact me directly.

Hire Me.

I provide custom solutions to complex problems. I can help your business no matter how large or small.

Contact me now.

Subscribe