10.19.2011

SPList Format and Display Web Part

In this project I will develop a web part which can be used as a display formatter for any SPList with any columns.
In other words what I want to do is to be able to take an ordinary list from SharePoint and display that list using my own html template. Similar to how you would use a repeater with your custom html template to display database items.





The Challenge
Since we would want this web part to work with any kind of list; the challenge we face is that some lists may or may not have attachments; they can have different column names and so forth. To overcome this issue we need to think of the web part as a generic ASP.net repeater.
Let's Start
  1. Launch Visual Studio 2008.
  2. Select File --> New --> Project.
  3. Select C# under Project Type.
  4. Select Web Part under Visual Studio Installed templates.
  5. Type RepeaterWebPart in the Name textbox.
  6. Select a location in your hard drive.
  7. Click on the OK Button to create the RepeaterWebPart web part.


Right-click on the Reference folder in the Solution Explorer and the select Add Reference...


Add the following references by going under the .NET table and then select the namespace and click OK:
(This is NOT required for this HelloWorld tutorial. But I included this step so that next time if you need to add a reference, you know how to?)
  • System.Data.LINQ
  • Microsoft.SharePoint
    (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.dll)


Open "AssemblyInfo.cs" from properties folder.


At the very end of the file enter the following code:
[assembly: AllowPartiallyTrustedCallers]   
 
And make sure to add the following namespace
using System.Security; 
 

 
Basic Setup
I always like to setup my class names in the web part first so that I can recognize it later within my SharePoint.
Open WebPart1.cs


Replace "WebPart1" from the line "public class WebPart1 :" with "public class ListDisplayWP" and replace "public WebPart1()" with "public ListDisplayWP()"


Writing the code
This web part may turn out to be pretty heavy. So, I will jump right into the code. If you need help, you may want to check out my beginner posts or send me a comment.
NameSpaces
Make sure you have following namespaces included on the top of the WebPart1.cs
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.ComponentModel;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using System.Collections.Generic;
 
Setting up Web Part Properties
Let's setup properties for the web part so that we can allow user to setup list variables.
Item Template Property
Right under public class ListDisplayWP : System.Web.UI.WebControls.WebParts.WebPart {
Enter the following block:
             //global vars
        String _ItemTemplate;
        SPSite site;
        SPWeb web;
        SPList Mylist;
        List ColumnNameList;

        #region Item Template Property

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [Category("Setup")]
        [WebDisplayName("Item Template")]
        [Description("Enter the template for the list. Enter column names as [name]")]
        [DefaultValue("setup")]
        public string ItemTemplate
        {
            get
            {
                return _ItemTemplate;
            }
            set
            {
                _ItemTemplate = value;
            }
        }

        #endregion

 
And then inside the function public ListDisplayWP(){ }
Place the following line:
           _ItemTemplate = "setup"; 
           
Our functions
Here are some functions that we will need in our web part. You can enter these after the CreateChildControls() function.
         private List GetColumnNames(string text)
        {
            List listColumns = new List();
            Regex regex = new Regex("\\[([\\sA-Za-z0-9-_]*)\\]");
            MatchCollection mathColl = regex.Matches(text);

            foreach (Match match in mathColl)
            {
                foreach (Group group in match.Groups)
                {
                    listColumns.Add(group.Value.Replace("[", "").Replace("]", ""));
                }
            }
            return listColumns;
        }


        public string getStringValue(Object ValueToChecka)
        {

            if (ValueToChecka != null)
                return ValueToChecka.ToString();
            else
                return "";

        }
        
  
The main Code
Our main code will be inside protected override void CreateChildControls()
Here we will write an algorithm which will:
  1. Call a function to extract the column names
  2. query the SPList
  3. plug in the values into the template and run it as a loop
Paste the following code inside the CreateChildControls() function.
            SPSite site = new SPSite("site url");
            SPWeb web = site.OpenWeb("subsite name if needed");
            SPList Mylist = web.Lists["My Test List"];
            String ItemTemplateRow = "";

            HtmlGenericControl MessageDiv = new HtmlGenericControl("div");
            MessageDiv.ID = "Messagediv";
            MessageDiv.InnerHtml = "";

            if (this.ItemTemplate == "setup")
                MessageDiv.InnerHtml = "Please enter a valid template";           
            else
            {
                //ItemName
                //this is where we will write the code for template

                // 1. Extract the column names
                ColumnNameList = GetColumnNames(this.ItemTemplate);

                // 2. Query the list
                foreach (SPListItem listItemc in Mylist.Items)
                {
                    ItemTemplateRow = this.ItemTemplate;

                    foreach (string columname in ColumnNameList)
                    {
                        try
                        {
                        ItemTemplateRow=ItemTemplateRow.Replace("[" + columname + "]", getStringValue(listItemc[columname]));
                        }
                        catch (ArgumentException ex)
                        {
                              MessageDiv.InnerHtml = "The column name ["+ columname +"] you entered does not exist. Please correct your settings" + ex.Message.ToString();

                        }

                    }

                    //listItemc["itemID"];
                    MessageDiv.InnerHtml += ItemTemplateRow;


                }






            }


            this.Controls.Add(MessageDiv);

            base.CreateChildControls();
That’s it. Your full code should look like:
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.ComponentModel;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace RepeaterWebPart
{
    [Guid("dba7a145-f926-43d3-bcbe-1300423fa1af")]
    public class ListDisplayWP : System.Web.UI.WebControls.WebParts.WebPart
    {
        //global vars
        String _ItemTemplate;
        SPSite site;
        SPWeb web;
        SPList Mylist;
        List ColumnNameList;

        #region Item Template Property

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [Category("Setup")]
        [WebDisplayName("Item Template")]
        [Description("Enter the template for the list. Enter column names as [name]")]
        [DefaultValue("setup")]
        public string ItemTemplate
        {
            get
            {
                return _ItemTemplate;
            }
            set
            {
                _ItemTemplate = value;
            }
        }

        #endregion


        public ListDisplayWP()
        {
            _ItemTemplate = "setup";
        }

        protected override void CreateChildControls()
        {
            SPSite site = new SPSite("site url");
            SPWeb web = site.OpenWeb("subsite name if needed");
            SPList Mylist = web.Lists["My Test List"];
            String ItemTemplateRow = "";

            HtmlGenericControl MessageDiv = new HtmlGenericControl("div");
            MessageDiv.ID = "Messagediv";
            MessageDiv.InnerHtml = "";

            if (this.ItemTemplate == "setup")
                MessageDiv.InnerHtml = "Please enter a valid template";           
            else
            {
                //ItemName
                //this is where we will write the code for template

                // 1. Extract the column names
                ColumnNameList = GetColumnNames(this.ItemTemplate);

                // 2. Query the list
                foreach (SPListItem listItemc in Mylist.Items)
                {
                    ItemTemplateRow = this.ItemTemplate;

                    foreach (string columname in ColumnNameList)
                    {
                        try
                        {
                        ItemTemplateRow=ItemTemplateRow.Replace("[" + columname + "]", getStringValue(listItemc[columname]));
                        }
                        catch (ArgumentException ex)
                        {
                              MessageDiv.InnerHtml = "<br/> The column name <strong>["+ columname +"]</strong> you entered does not exist. Please correct your settings <br/>" + ex.Message.ToString();

                        }

                    }

                    //listItemc["itemID"];
                    MessageDiv.InnerHtml += ItemTemplateRow;


                }






            }


            this.Controls.Add(MessageDiv);

            base.CreateChildControls();

        }

        private List GetColumnNames(string text)
        {
            List listColumns = new List();
            Regex regex = new Regex("\\[([\\sA-Za-z0-9-_]*)\\]");
            MatchCollection mathColl = regex.Matches(text);

            foreach (Match match in mathColl)
            {
                foreach (Group group in match.Groups)
                {
                    listColumns.Add(group.Value.Replace("[", "").Replace("]", ""));
                }
            }
            return listColumns;
        }


        public string getStringValue(Object ValueToChecka)
        {

            if (ValueToChecka != null)
                return ValueToChecka.ToString();
            else
                return "";

        }

    }
}


Now we will deploy the web part.
Deploying the web part
Now we need to deploy our web part.
  1. Build the solution

  2. If no error returned by the compiler, copy the DLL from your Birthday project bin > Debug directory to the bin directory of your WSS site (C:\Inetpub\wwwroot\wss\VirtualDirectories\80\bin).




  3. Go to (C:\inetpub\wwwroot\wss\VirtualDirectories\80\) and modify the Web.Config file for the WSS site to declare the custom web part as a safe control by adding the following code within the <SafeControls> tag.
 <SafeControl Assembly="RepeaterWebPart" Namespace="RepeaterWebPart" TypeName="*" Safe="True" />



Now we can walk through, How to insert this web part in our SharePoint Page?
  1. Go to your root SharePoint site and from there Site Actions -> Site Settings -> Modify All Site Setting.


  2. Under “Galleries" tab click "Web Parts" link.


  3. Add a new web part, Click New menu in web part gallery Page.



  4. Select the newly added web part in the "New Parts Page" and click on "populate gallery"


  5. If the import is successful, you will see the web part in Web part gallery list.

Now we see How to insert into a SharePoint Page?
  1. Create a blank web part page and name it HelloWorldPage
  2. Once the page is created, click on "Add a Web Part"

  3. From the web part list, locate the one we just created and add.
Running the web part
If all went well in previous steps, you should see "please enter a valid template"


Modify the web part properties and enter the following template:





<table>
<tr>
<td>Item Name: [ItemName]</td>
<td>Item Price:[Item Price]</td>
</tr>
</table>



Notice that i entered this template for an existing list on my SharePoint server "my test list". That list has the columns "ItemName" and "Item Price". I also used this list's name in the code. You may need to change the column names and list name to what you have setup.

 
So once we save the template, the web part should run.




happy programming!

0 comments:

Post a Comment

Contact Form

Name

Email *

Message *

 
POPULAR POSTS
TAG CLOUD