How to use ASCX controls in portlets

From Sense/Net Wiki
Jump to: navigation, search
  •  
  •  
  •  
  •  
  • 100%
  • 6.0
  • Enterprise
  • Community
  • Planned

Overview

A portlet is a common way to implement custom UI on Sense/Net pages (see How to create and install a Portlet). Defining UI elements and logic in portlet code however makes the UI hard to be fine-adjusted or modified by builders, without rebuilding the full solution. Therefore it is advisable to use ascx controls to define the UI and use the portlet only to display it.

Steps

1. Create a new class

Let's create an ascx first with its code behind. Create a new Web User Control in your web application - the code behind file will automatically be created for your ascx by Visual Studio. See the following guide on how to create a new item in your source code (since we create an ascx, your project must be a web application):

2. Separate ascx and code-behind

Since our .ascx file will be persisted in the content repository, let's move it to the Root structure. If you use the standard Sense/Net development environment, the target should be the Root folder in your web application (let's chose an appropriate location in the repository, like /Root/Global/plugins/myportlet). This will move the code behind as well, but we will not upload cs files to the repository, so let's delete every file under the ascx file! We still need the code behind, so let's add a new class under the 'Code' folder with the name WebUserControl1.cs and paste the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace MyWebApplication
{
    public partial class WebUserControl1 : System.Web.UI.UserControl
    {
    }
}

Let's create the designer file, too - so that it will be easier to reference controls. Create a new class and name it WebUserControl1.designer.cs. The contents will be auto-generated by Visual Studio. Now let's adjust the codebehind markup of the ascx, so this should be the contents of the ascx file:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="~/Code/WebUserControl1.cs" Inherits="MyWebApplication.WebUserControl1" %>

Your project structure should look like the following:

Project structure for ascx and codebehind

3. Implement your ascx code

Let's implement the UI! Paste the following code into our ascx file:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="~/Code/WebUserControl1.cs" Inherits="MyWebApplication.WebUserControl1" %>
 
<asp:TextBox ID="MyText" runat="server" />
<asp:Button ID="MyButton" runat="server" Text="Push me" />

Here we defined a button and a textbox. Notice, that the corresponding designer code-behind was auto-generated by Visual Studio upon save:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated. 
// </auto-generated>
//------------------------------------------------------------------------------
 
namespace MyWebApplication {
 
 
    public partial class WebUserControl1 {
 
        /// <summary>
        /// MyText control.
        /// </summary>
        /// <remarks>
        /// Auto-generated field.
        /// To modify move field declaration from designer file to code-behind file.
        /// </remarks>
        protected global::System.Web.UI.WebControls.TextBox MyText;
 
        /// <summary>
        /// MyButton control.
        /// </summary>
        /// <remarks>
        /// Auto-generated field.
        /// To modify move field declaration from designer file to code-behind file.
        /// </remarks>
        protected global::System.Web.UI.WebControls.Button MyButton;
    }
}

Let's add some business logic, too! If the user clicks the button, let's display something in the textbox:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace MyWebApplication
{
    public partial class WebUserControl1 : System.Web.UI.UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            this.MyButton.Click += new EventHandler(MyButton_Click);
            base.OnInit(e);
        }
 
        void MyButton_Click(object sender, EventArgs e)
        {
            this.MyText.Text = "Button was pushed";
        }
    }
}

We are ready, but we still need a portlet to display the above control.

4. Implement your portlet code

We will create a very simple portlet, that will host our ascx control. Add a new class to the project and paste the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SenseNet.Portal.UI.PortletFramework;
 
namespace MyWebApplication.Code
{
    public sealed class MyPortlet : PortletBase
    {
        private const string _MYCONTROLPATH = "/Root/Global/plugins/myportlet/WebUserControl1.ascx";
        private System.Web.UI.Control _myControl;
 
        public MyPortlet()
        {
            this.Name = "MyPortlet";
            this.Description = "Put description here.";
            this.Category = new PortletCategory(PortletCategoryType.Application);
        }
 
        protected override void OnInit(EventArgs e)
        {
            _myControl = this.Page.LoadControl(_MYCONTROLPATH);
            this.Controls.Add(_myControl);
 
            base.OnInit(e);
        }
    }
}

What we do here is simply reference the ascx control and add it to the control collection of the portlet. Note: we could also directly access controls of the loaded control if we added the following:

        public System.Web.UI.WebControls.Button MyButton
        {
            get
            {
                return _myControl.FindControl("MyButton") as System.Web.UI.WebControls.Button;
            }
        }

This is of course a little more work, than accessing the controls from the ascx code-behind (what we did in step 3), since these properties are auto-generated by Visual Studio.

If you only want to host an ascx in your portlet and not implement any further logic, you can use the built-in User Control Portlet for that. Just add it to a page and set the path of your ascx in its portlet properties!

We are ready, let's deploy!

5. Deploy ascx and portlet

  1. Upload the ascx file to /Root/Global/plugins/myportlet
  2. Install the portlet (like in How to create and install a Portlet)

6. Test portlet

Choose an existing page or create a new page, and add the portlet to a zone. This is what you should see:

Portlet with custom ascx

Now we have a custom portlet with a UI defined in a custom ascx. This way we have separated the business logic from the UI and thus enabled our builders to implement a custom design without modifying the code-behind.

Related links

References

There are no related external articles for this article.