Friday, August 19, 2011

Creating Custom SPGridView – Part 1

In this blog we will see the simplest way to create a SPGridView, the basic steps would be :

1.     Set property AutoGenerateColumns to false

2.     Create Columns as SPBoundField and associate te Data field to the Data source field

3.     Bind the SPGridView to the datasource and that is it

 

Let us now get to the code and see the how easily a simple SPGridView is done. I have created this inside a web part. In future blogs I would like to explore rich functionalities of the SPGridView and their usage. This SPGridView control is used in the all the list views. Thus, if required we can create similar grid views using this rich control.

I am providing the whole code in one go with some comments in between the code lines.

public class MySPGridViewProjects: System.Web.UI.WebControls.WebParts.WebPart

{

/// <summary>

/// Creates a SPGridView similar to list with custom functionalities

/// </summary>

#region Variables + Controls

Table table;

SPGridView spgvAllProjects;

#endregion

#region Create Child Controls

protected override void CreateChildControls()

{

base.CreateChildControls();

try

{

//Create Controls

      table = new Table();

      this.Controls.Add(table);

      ////All Projects GridView

      spgvAllProjects = new SPGridView();

      spgvAllProjects.ID = "spgvAllProjects";

      spgvAllProjects.AutoGenerateColumns = false;

      spgvAllProjects.RowStyle.BackColor = Color.LightGray;

      spgvAllProjects.AlternatingRowStyle.BackColor = Color.White;

      //----Add to Table ---

      TableRow trAllProjGrid = new TableRow();

      TableCell tcAllProjGrid = new TableCell();

      tcAllProjGrid.Controls.Add(spgvAllProjects);

      trAllProjGrid.Cells.Add(tcAllProjGrid);

      table.Rows.Add(trAllProjGrid);

      ////Active Projects

      PopulateAllProjects("Title", "asc");

      ////Set Web Part Properties

      this.ChromeType = PartChromeType.TitleOnly;

      this.Title = "All Projects";

}

catch (Exception ex)

{

String Message = ex.Message;

}

}

#endregion

Now before I move further, I would like to say that I did not take the pain to create a data table to bind to the SPGridView. For keeping it short I have used the data from a simple list. If you want you can create a data source of your choice. In this case I have taken all the items available from MyList. While creating the bound fields please keep in mind that the data fields should match to the Field names of the List.

#region Populate All Projects

private void PopulateAllProjects(string SortExpression, string NewSortDirection)

{

////Get the Selected Project IDs

      #region Grid View Fields

      SPBoundField boundField = new SPBoundField();

      boundField.HeaderText = "Project ID";

      boundField.DataField = "Title";

      boundField.ControlStyle.CssClass = "ms-vb2";

      spgvAllProjects.Columns.Add(boundField);

 

      boundField = new SPBoundField();

      boundField.HeaderText = "Project Name";

      boundField.DataField = "Name";

      boundField.ControlStyle.CssClass = "ms-vb2";

      spgvAllProjects.Columns.Add(boundField);

 

     

boundField = new SPBoundField();

      boundField.HeaderText = "Project Manager";

////Filed name has got a space inbetween

      boundField.DataField = "Project_x0020_Manager";

      boundField.ControlStyle.CssClass = "ms-vb2";

      spgvAllProjects.Columns.Add(boundField);

     

////The Hidden column to populate Status with image, we will see this

//// Part 2 of creating custom spgridview

      boundField = new SPBoundField();

      boundField.HeaderText = "Status";

      boundField.DataField = "Status";

      boundField.ControlStyle.CssClass = "ms-vb2";

      boundField.Visible = false;

      spgvAllProjects.Columns.Add(boundField);

 

//// Get the data source

      DataTable dt = GetAllProjectsToDisplay();

      try

      {

        if (dt != null && dt.Rows.Count > 0)

        {

            DataView dv = new DataView(dt);

            ////Sort the DataView

            if (!string.IsNullOrEmpty(SortExpression) && !string.IsNullOrEmpty(NewSortDirection))

            {

                  dv.Sort = SortExpression + " " + NewSortDirection;

            }

            ////DG data source

            spgvAllProjects.DataSource = dv;

            ////Data binding

            spgvAllProjects.DataBind();

         }

       }

       catch (Exception ex)

       {

       PortalLog.LogString("Exception in - Create Child Control :" + ex.Message);

        }

 }

////Get your data to display

#region Get Data Source

private DataTable GetAllProjectsToDisplay()

{

DataTable dt = null;

      SPWeb oWeb = SPContext.Current.Web;

      SPList oList = oWeb.Lists[“MyList”];

      try

      {

       ////Run a query to fetch All Project Data

       SPQuery oSPquer = new SPQuery();

       oSPquer.Query = "<Where><And><Eq></Eq></And></Where>";

       SPListItemCollection oItemColl = oList.GetItems(oSPquer);

       if (oItemColl.Count > 0)

           {

                dt = oItemColl.GetDataTable();

           }

       }

       catch (Exception ex)

       {

       }

       return dt;

 }

#endregion

 

Hopefully you have the GridView ready. This was very simple, though you could find some extra bit of coding. These have been kept for the Part 2, where we will add sorting, filtering, paging, menu field etc., to enrich our GridView.


If you have a more elegant solution – please post a comment… I’ll be happy to hear. Thanks for reading.

...HaPpY CoDiNg

Partha (Aurum)

 

 

Thursday, August 18, 2011

Difference between UsageDetails.aspx and SPUsageWeb.aspx

 

When a colleague of mine asked me the difference between the site usage pages available under Site Administration in the site settings page, I had to dig to get the answer and here it now sharing with you now. Smile

 

clip_image002

The page itself was different for two different site

1.     Site 1 was showing  - UsageDetails.aspx (http://myserver/site1/_layouts/usageDetails.aspx )

2.     Site 2 was showing – SPUsageWeb.aspx(http://myserver/site1/_layouts/SPUsageWeb.aspx )

 

 

After going thru some the articles available over net, I could realize that it is due to the type of feature that is activated.

a.       Office SharePoint Server Enterprise Site features

b.      Office SharePoint Server Standard Site features

clip_image004

Basically if you are using plain WSS then you would see the usageDetails.aspx page for usage reporting and if you are using MOSS (SharePoint 2007) with both STDANDARD and ENTERPRISE features enabled then you would be directed to the SpUsageWeb.aspx page. Even only enabling enterprise feature would provide the SPUsageWeb page which has more intuitive and graphical representation of the site usage data.


Thanks for reading. If you have some other explanation – please post a comment… I’ll be happy to hear.

...HaPpY CoDiNg

Partha (Aurum)

 

Similar topics:

why some sites show UsageDetails.aspx and not SPUsageWeb.aspx

Tuesday, August 16, 2011

String Array Contains method does not work

 

I was trying to find out an elegant way to find whether an item exists in an array elements and found the contains method. But, for some reason it was not working directly the string[]strArr.Contains(item) for me. Tried in one windows application and it worked L, more confused, I started to figure out why?  I was wondering why the Contains method is not working and got the below solution. The idea is somewhat to achieve the below example

 

string[] ItemColletion = ....;
if (ItemColletion.Contains(“item”
))
{
    ...
}

In .NET 3.5 this is possible out of the box (make sure you reference System.Core and include the System.Linq namespace) but if you try to run this code in .NET 2.0 or .NET 3.0 you will get errors.

'System.Array' does not contain a definition for 'Contains' and no extension method 'Contains' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

Nevertheless the .NET Framework 2.0 does provide a Contains() method on any Array object. In the .NET Framework 2.0, System.Array implements the System.Collections.Generic.IList<T> interface. Unfortunately the implementation of the IList interface is provided at runtime so we do not see the methods in Visual Studio and we cannot write array.Contains(). Instead we have to cast the array to the appropriate IList interface before we can use the Contains method. See below an example:

 

string[] ItemCollection = new string[] {“Blue”,“Red”,“Green”};
if (!((IList<string>)ItemCollection).Contains(“Green”))
{
  
//Do something .....

}


 

MSDN Explanation:

http://msdn.microsoft.com/en-us/library/system.array(v=vs.80).aspx

clip_image001[4]Important:

In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic.IList, System.Collections.Generic.ICollection, and System.Collections.Generic.IEnumerable generic interfaces. The implementations are provided to arrays at run time, and therefore are not visible to the documentation build tools. As a result, the generic interfaces do not appear in the declaration syntax for the Array class, and there are no reference topics for interface members that are accessible only by casting an array to the generic interface type (explicit interface implementations). The key thing to be aware of when you cast an array to one of these interfaces is that members which add, insert, or remove elements throw NotSupportedException.

 

So you can now save yourself from looping thru the array to find an item. Rather use the Contains method and let framework work for you. J

Thanks for reading, If you have a more elegant solution – please post a comment… I’ll be happy to hear.

...HaPpY CoDiNg

Partha (Aurum)

Array Contains method does not work

Wednesday, August 3, 2011

Creating Dynamic DataList control with ITemplate in C#

 

 

A bit of information on Templates available

Templates

The contents of the DataList control can be manipulated by using templates. The following table lists the supported templates.

Template Name

Description

AlternatingItemTemplate

If defined, provides the content and layout for alternating items in the DataList. If not defined, ItemTemplate is used.

EditItemTemplate

If defined, provides the content and layout for the item currently being edited in the DataList. If not defined, ItemTemplate is used.

FooterTemplate

If defined, provides the content and layout for the footer section of the DataList. If not defined, a footer section will not be displayed.

HeaderTemplate

If defined, provides the content and layout for the header section of the DataList. If not defined, a header section will not be displayed.

ItemTemplate

Required template that provides the content and layout for items in the DataList.

SelectedItemTemplate

If defined, provides the content and layout for the currently selected item in the DataList. If not defined, ItemTemplate is used.

SeparatorTemplate

If defined, provides the content and layout for the separator between items in the DataList. If not defined, a separator will not be displayed.

At the very minimum, the ItemTemplate needs to be defined to display the items in the DataList control. Additional templates can be used to provide a custom look to the DataList control.

For more read:

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.datalist.aspx

 

The use of custom template class to show desired data from inside the .cs class in C# could be easily achieved by having a custom class which will inherit from the ITemplate interface and manipulating the InstantiateIn Method

 

Let us get to the code for better understanding. We will first see the custom template class as MyTemplate. It will create the link items.

 

public class MyTemplate : ITemplate

{

    ListItemType ItemType;

    public MyTemplate(ListItemType _ItemType)

    {

        ItemType = _ItemType;

    }

    //This is the implentation fo the ITemplate interface

    #region ITemplate Members

    public void InstantiateIn(Control container)

    {

        Literal lc = new Literal();

        LinkButton lbItem = new LinkButton();

        //Determining which type of ListItem has come header or item etc.

        switch (ItemType)

        {

            case ListItemType.Header:

                lc.Text = "<div id=\"nifty\" class=\"PostCategory\">Header</div>";

                break;

            case ListItemType.Item:

                lc.DataBinding += new EventHandler(lc_DataBinding);

                break;

            case ListItemType.SelectedItem:

                lc.Text = "<div style='background-color:Red'><A href=# >Test Link</a></div> ";

                break;

            case ListItemType.Footer:

                lc.Text = "<div style=\"text-align:right\">Footer</div>";

                break;

        }

        //Adding to the container - here container is the DataList

        container.Controls.Add(lc);

    }

    private void lc_DataBinding(object sender, System.EventArgs e)

    {

        Literal lc = (Literal)sender;

        DataListItem container = (DataListItem)lc.NamingContainer;

        lc.Text += "<div style='background-color:#FFFFCC'><A href=" + DataBinder.Eval(container.DataItem, "Links") + ">" + DataBinder.Eval(container.DataItem, "Links") + " </a></div> ";

    }

    #endregion

}

 

Now to let us see how to use this class. Need to define which template and call accordingly.

 

#region Controls  + Variables

    Panel pnlControlPlaceHolder;

    #endregion

 

    protected void Page_Load(object sender, EventArgs e)

    {

        pnlControlPlaceHolder = new Panel();

        DataList myDataListL = new DataList();

        ////Populate Data

        DataTable dt = new DataTable();

        dt.Columns.Add("Links");

        DataRow dr;

        for (int i = 1; i < 10; i++)

        {

            dr = dt.NewRow();

            dr["Links"] = "A" + i;

            dt.Rows.Add(dr);

            dt.AcceptChanges();

        }

        //Data List propertise + Data bind

        myDataListL.RepeatDirection = RepeatDirection.Horizontal;

        myDataListL.RepeatColumns = 5;

        if (dt.Rows.Count > 0)

        {

            myDataListL.HeaderTemplate = new MyTemplate(ListItemType.Header);

            myDataListL.FooterTemplate = new MyTemplate(ListItemType.Footer);

            myDataListL.ItemTemplate = new MyTemplate(ListItemType.Item);

            myDataListL.SelectedItemTemplate = new MyTemplate(ListItemType.SelectedItem);

            myDataListL.Width = Unit.Percentage(100);

            myDataListL.GridLines = GridLines.Both;

            myDataListL.DataSource = dt;

            myDataListL.DataBind();

            pnlControlPlaceHolder.Controls.Add(myDataListL);

        }

        this.Controls.Add(pnlControlPlaceHolder);

    }

 

I have used this in an asp.net page to populate the controls. You just need to add this code in the code behind class of the aspx page.


If you have a more elegant solution – please post a comment… I’ll be happy to hear. Thanks for reading.

...HaPpY CoDiNg

Partha (Aurum)