hOne piece of SharePoint toolbox, rarely used, and not well known, is a SPGridView control, a SharePoint wrapper over a standard .NET GridView control.
Since the SPGridView is not well documented, and implementing standard functionality with it is somewhat painful, I have developed a wrapper around it, which can be used to bind the control at runtime by using bindable data sources.
This piece od code is from my upcoming session on Microsoft WinDays 2008.
Hope it helps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Diagnostics;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Data;
using System.Web.UI;
using System.Collections;
namespace Daenet.SharePointApi
{
#region DaenetSPGridView
///
///
public class DaenetSPGridView : SPGridView
{
#region public properties
///
///
public string FieldsToDisplay { get; set; }
///
///
public string FieldsHeaders { get; set; }
///
///
public string SortFields { get; set; }
///
///
public string MenuField { get; set; }
///
///
public object GridDataSource { get; set; }
#endregion
#region private fields
///
///
string[] m_ColumnNames;
///
///
string[] m_HeaderNames;
#endregion
#region constructor
///
///
/// ID of the newly created grid
/// Row alternate color – leave empty if no alternate color
/// DataSource object we want to use as the grid source
/// Fields we want to display in grid, comma separated
/// Headers of the fields we want to display
/// Fields we want to enable sorting onto, comma separated
/// Fields we want to enable filtering onto, comma separated, in the “FilterDataFields” mode
/// Do we want to enable paging? 0 – no, n-number of the rows per page
/// Set the grouping field if we want to enable grouping
public DaenetSPGridView(string gridName, Color alternateColor, object gridDataSource, string displayFields, string fieldHeaders, string sortFields, string filteredFields, int pageSize, string groupingField, string menuField)
{
// Set basic gridview properties
this.ID = gridName;
this.AutoGenerateColumns = false;
if (alternateColor != null) this.AlternatingRowStyle.BackColor = alternateColor;
//set properties
GridDataSource = gridDataSource;
FieldsToDisplay = displayFields;
FieldsHeaders = fieldHeaders;
SortFields = sortFields;
MenuField = menuField;
//generate grid coumns
generateColumns();
//
//set filtering
if (!string.IsNullOrEmpty(filteredFields))
{
// Set properties for filtering
this.AllowFiltering = true;
this.FilterDataFields = filteredFields;
this.FilteredDataSourcePropertyName = “FilterExpression”;
this.FilteredDataSourcePropertyFormat = “{1} LIKE ‘{0}'”;
this.RowDataBound += new GridViewRowEventHandler(gridView_RowDataBound);
}
if (!string.IsNullOrEmpty(sortFields))
{
this.AllowSorting = true;
}
if (pageSize != 0)
{
// Set properties for paging
this.PageSize = pageSize;
this.AllowPaging = true;
this.PagerStyle.HorizontalAlign = HorizontalAlign.Right;
}
if (!string.IsNullOrEmpty(groupingField))
{
//AllowGrouping=”true” AutoGenerateColumns=”false” GroupField=”StateName”
//AllowGroupCollapse=”true” DisplayGroupFieldName=”false”>
this.AllowGrouping = true;
this.GroupField = groupingField;
this.AllowGroupCollapse = true;
this.DisplayGroupFieldName = true;
}
}
#endregion
#region public methods
public void SetColumnMenu(string columnName)
{
try
{
//
//TODO:
//1 – item Click – UrlFields
//2 – item Click – UrlFormat
//
//first hide the original column
DataControlField originalColumn = findColumnFromHeaderText(getHeaderTextFromColumnId(columnName));
string originalHeaderText = originalColumn.HeaderText;
originalColumn.HeaderText += “-OLD”;
originalColumn.Visible = false;
//
// Replace the Original coloumn with a shiny menu
SPMenuField colMenu = new SPMenuField();
colMenu.HeaderText = originalHeaderText;
colMenu.TextFields = columnName;
colMenu.MenuTemplateId = columnName + “Menu”;
colMenu.NavigateUrlFields = “ID,Title”;
colMenu.NavigateUrlFormat = “do.aspx?p={0}&q={1}”;
colMenu.TokenNameAndValueFields = “EDIT=ID,NAME=Title”;
colMenu.SortExpression = columnName;
//
//generate dropdown
MenuTemplate presenterListMenu = new MenuTemplate();
presenterListMenu.ID = columnName + “PresenterListMenu”;
//
//generate dropdownitems
MenuItemTemplate biogMenu = new MenuItemTemplate(
“Read Biography”, “/_layouts/images/EawfNewUser.gif”);
biogMenu.ClientOnClickNavigateUrl = “do.aspx?this=%EDIT%&that=%NAME%”;
presenterListMenu.Controls.Add(biogMenu);
MenuItemTemplate broadcastMenu = new MenuItemTemplate(
“Recent Broadcasts”, “/_layouts/images/ICWM.gif”);
broadcastMenu.ClientOnClickNavigateUrl = “do.aspx?this=%EDIT%&that=%NAME%”;
presenterListMenu.Controls.Add(broadcastMenu);
//separator
MenuSeparatorTemplate sepMenu = new MenuSeparatorTemplate();
presenterListMenu.Controls.Add(sepMenu);
MenuItemTemplate favMenu = new MenuItemTemplate(
“Add to Favorites”, “/_layouts/images/addtofavorites.gif”);
favMenu.ClientOnClickNavigateUrl = “do.aspx?this=%EDIT%&that=%NAME%”;
presenterListMenu.Controls.Add(favMenu);
//add presenter menu to the controls collection
this.Controls.Add(presenterListMenu);
//add column with menu temlae
this.Columns.Add(colMenu);
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw;
}
}
///
///
///
///
public void SetColumnWidth(string columnName, Unit widthUnit)
{
try
{
DataControlField column = findColumnFromHeaderText(getHeaderTextFromColumnId(columnName));
column.ControlStyle.Width = widthUnit;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw;
}
}
#endregion
#region private methods
///
///
private void generateColumns()
{
try
{
m_ColumnNames = FieldsToDisplay.Split(“,”.ToCharArray());
m_HeaderNames = FieldsHeaders.Split(“,”.ToCharArray());
List
string menuFieldName = “”;
string[] menuFieldInfo = new string[]{};
if (!string.IsNullOrEmpty(MenuField))
{
menuFieldInfo = MenuField.Split(“,”.ToCharArray());
menuFieldName = menuFieldInfo[0];
}
//retrieve underlaying data from the DataSource
//IEnumerable underlayingDataTable = ((IEnumerable)(((ObjectDataSource)(GridDataSource)).Select()));
IEnumerable enumerableData = ((IEnumerable)(((ObjectDataSource)(GridDataSource)).Select()));
//
//iterate through the columns we want to display
for (int i = 0; i < m_ColumnNames.Length; i++)
{
if (m_ColumnNames[i] != menuFieldName)
{
BoundField colName = new BoundField();
colName.DataField = m_ColumnNames[i];
colName.HeaderText = m_HeaderNames[i];
if (sortFieldsList.Contains(m_ColumnNames[i])) colName.SortExpression = m_ColumnNames[i];
this.Columns.Add(colName);
}
else
{
/*
*
* */
SPMenuField colName = new SPMenuField();
colName.NavigateUrlFields = “ID”;
colName.NavigateUrlFormat = menuFieldInfo[1];//”StoreManager.aspx?ID={0}
colName.TextFields = m_ColumnNames[i];
colName.HeaderText = m_HeaderNames[i];
colName.TokenNameAndValueFields = “ID=ID”;
colName.MenuTemplateId = menuFieldInfo[2];
this.Columns.Add(colName);
}
}
}
catch (Exception ex)
{
throw new ApplicationException(“Formatted SharePoint Grid Exception”, ex);
}
}
/*
///
///
private void generateColumns()
{
try
{
m_ColumnNames = FieldsToDisplay.Split(“,”.ToCharArray());
m_HeaderNames = FieldsHeaders.Split(“,”.ToCharArray());
List
//retrieve underlaying data from the DataSource
DataTable underlayingDataTable = ((DataView)(((ObjectDataSource)(GridDataSource)).Select())).Table;
//
//iterate through the columns we want to display
for (int i = 0; i < m_ColumnNames.Length; i++)
{
DataColumn col = underlayingDataTable.Columns[m_ColumnNames[i]];
Type colType = col.DataType;
//
//string and numeric fields
if (colType == typeof(string) || colType == typeof(int) || colType == typeof(double))
{
BoundField colName = new BoundField();
colName.DataField = m_ColumnNames[i];
colName.HeaderText = m_HeaderNames[i];
if (sortFieldsList.Contains(m_ColumnNames[i])) colName.SortExpression = m_ColumnNames[i];
this.Columns.Add(colName);
}
//
//checkbox fields
if (colType == typeof(bool))
{
TemplateField colName = new TemplateField();
colName.HeaderText = m_HeaderNames[i];
colName.ItemTemplate = new CheckBoxItemTemplate(ListItemType.Item, m_ColumnNames[i]);
if (sortFieldsList.Contains(m_ColumnNames[i])) colName.SortExpression = m_ColumnNames[i];
this.Columns.Add(colName);
}
}
}
catch (Exception ex)
{
throw new ApplicationException("Formatted SharePoint Grid Exception", ex);
}
}
*/
///
/// We catch the gridView_RowDataBound event, check if it is a header row
/// and if it is header row, set the icon on the cell of the corresponding column
///
///
///
private void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
//first check if it is a header row
if ((sender != null) && (e.Row.RowType == DataControlRowType.Header))
{
//get the filter field name (ID of the field)
string strFilteredColumn = ((DaenetSPGridView)sender).FilterFieldName;
//get the header name from the field name
string headerText = getHeaderTextFromColumnId(strFilteredColumn);
//set the icon
if (!string.IsNullOrEmpty(headerText))
SetGridViewFilterIcon(headerText, e.Row);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
///
///
/// Header text of the column we are setting the icon to
/// Grid row of the cell we want to set the icon to – has to be the header row
public void SetGridViewFilterIcon(string columnHeaderText, GridViewRow row)
{
try
{
if ((!string.IsNullOrEmpty(columnHeaderText)) && (row != null))
{
//
//find an index of the column we are searching for
int column = findColumnIndexFromHeaderText(columnHeaderText);
//
//if column index found, set the icon
if (column != -1)
{
addIconToCell(row.Cells[column], “filterIcon”, “/_layouts/images/ewr093.gif”, ImageAlign.Left, “2px”, “”, “”, “”);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
throw;
}
}
///
/// since we do not have IDs there.
///
/// Header text of the column we are searching for
///
private DataControlField findColumnFromHeaderText(string headerText)
{
for (int iIndex = 0; iIndex < this.Columns.Count; iIndex++)
{
DataControlField oField = this.Columns[iIndex];
if (oField.HeaderText == headerText) return oField;
}
return null;
}
///
/// since we do not have IDs there.
///
/// Header text of the column we are searching for
///
private int findColumnIndexFromHeaderText(string headerText)
{
for (int iIndex = 0; iIndex < this.Columns.Count; iIndex++)
{
DataControlField oField = this.Columns[iIndex];
if (oField.HeaderText == headerText) return iIndex;
}
return -1;
}
///
///
/// column Id we are lookinf for
///
private string getHeaderTextFromColumnId(string columnId)
{
try
{
int columnPosition = m_ColumnNames.ToList
if (columnPosition >= 0)
{
return m_HeaderNames[columnPosition];
}
else
{
return null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
throw;
}
}
///
///
///
///
private static void addIconToCell(TableCell cellToAddIcon, string iconId, string imageUrl, ImageAlign align, string marginTop, string marginLeft, string marginRight, string marginBottom)
{
System.Web.UI.WebControls.Image oFilterIcon = new System.Web.UI.WebControls.Image();
oFilterIcon.ImageUrl = imageUrl;
oFilterIcon.ImageAlign = align;
if (!string.IsNullOrEmpty(marginTop)) oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginTop] = marginTop;
if (!string.IsNullOrEmpty(marginLeft)) oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginLeft] = marginLeft;
if (!string.IsNullOrEmpty(marginRight)) oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginRight] = marginRight;
if (!string.IsNullOrEmpty(marginBottom)) oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginBottom] = marginBottom;
oFilterIcon.ID = iconId;
Panel oPanel = new Panel();
oPanel.Controls.Add(oFilterIcon);
//”2px”
//ImageAlign.Left
//”/_layouts/images/ewr093.gif”
//GridViewRow oRow, int iIndex
//oRow.Cells[iIndex]
cellToAddIcon.Controls.Add(oPanel);
}
#endregion
#region overrides
///
///
///
protected override void LoadControlState(object savedState)
{
base.LoadControlState(savedState);
if (this.DataSource == null)
{
this.DataBind();
}
}
#endregion
}
#endregion
//
//Item Template classes
#region Item template classes
///
///
public class CheckBoxItemTemplate : ITemplate
{
///
///
private ListItemType m_ItemType;
///
///
private string m_FieldName;
///
///
/// Item Type – to determine if the item is header or list item
/// Field name we are setting
public CheckBoxItemTemplate(ListItemType itemType, string fieldName)
{
m_ItemType = itemType;
m_FieldName = fieldName;
}
public void InstantiateIn(System.Web.UI.Control controlContainer)
{
if (m_ItemType == ListItemType.Item || m_ItemType == ListItemType.SelectedItem || m_ItemType == ListItemType.AlternatingItem)
{
System.Web.UI.WebControls.Image checkIcon = new System.Web.UI.WebControls.Image();
checkIcon.ImageAlign = ImageAlign.Middle;
checkIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginTop] = “2px”;
checkIcon.ID = “CheckIcon_” + m_FieldName;
checkIcon.Visible = true;
checkIcon.DataBinding += new EventHandler(cb_DataBinding);
controlContainer.Controls.Add(checkIcon);
}
}
///
///
///
///
private void cb_DataBinding(object sender, EventArgs e)
{
System.Web.UI.WebControls.Image imageSender = (System.Web.UI.WebControls.Image)(sender);
SPGridViewRow parentRow = (SPGridViewRow)(imageSender.NamingContainer);
try
{
bool cbChecked = (bool)(DataBinder.Eval(parentRow.DataItem, m_FieldName));
if (cbChecked)
{
imageSender.ImageUrl = “/_layouts/images/CHECK.GIF”;
}
else
{
imageSender.ImageUrl = “/_layouts/images/UNCHECK.GIF”;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
imageSender.ImageUrl = “/_layouts/images/UNCHECK.GIF”;
}
}
}
#endregion
}
public class OdsDataViewWrapper
{
///
///
public static DataTable DataToDisplay { get; set; }
///
///
public static IEnumerable ObjectToDisplay { get; set; }
///
///
public OdsDataViewWrapper() { }
///
///
///
public static System.Data.DataTable GetData()
{
if (DataToDisplay == null)
{
return new DataTable();
}
else
{
return DataToDisplay;
}
}
///
///
///
public static IEnumerable GetObjectData()
{
if (ObjectToDisplay == null)
{
List
dummyStringList.Add(“No”);
dummyStringList.Add(“Data”);
return dummyStringList;
}
else
{
return ObjectToDisplay;
}
}
public static int UpdateAuthor(string au_id, string au_lname, string au_fname, string state)
{
return 1;
}
///
///
/// ID of the ObjectDataSource
/// DataTable from which we want to display data
///
public static ObjectDataSource GetObjectDataSource(string odsID, DataTable dataTable)
{
DataToDisplay = dataTable;
ObjectDataSource ods = new ObjectDataSource();
ods.ID = odsID;
ods.TypeName = “Daenet.SharePointApi.OdsDataViewWrapper”;
ods.SelectMethod = “GetData”;
OdsDataViewWrapper.DataToDisplay = dataTable;
return ods;
}
///
///
/// ID of the ObjectDataSource
/// DataTable from which we want to display data
///
public static ObjectDataSource GetObjectDataSource(string odsID, IEnumerable objectSource)
{
ObjectToDisplay = objectSource;
ObjectDataSource ods = new ObjectDataSource();
ods.ID = odsID;
ods.TypeName = “Daenet.SharePointApi.OdsDataViewWrapper”;
ods.SelectMethod = “GetObjectData”;
OdsDataViewWrapper.ObjectToDisplay = objectSource;
return ods;
}
///
///
/// HttpRequest object where we are checking if the Filter was earlier set
/// SPGridView for which we are setting the Filter
/// Key in the viewstate where we are storing current filter expression
/// ViewState collection where we are storing the current filter expression
public static bool CheckRequestForFilterExpression(HttpRequest httpRequest, DaenetSPGridView gridView, string expressionKeyName, StateBag viewState)
{
if ((httpRequest.Form[“__CALLBACKID”] == null) ||
(httpRequest.Form[“__CALLBACKPARAM”] == null) ||
(!httpRequest.Form[“__CALLBACKID”].EndsWith(gridView.ID)))
{
if (viewState[expressionKeyName] != null)
{
return true;
}
}
return false;
}
///
///
/// ID of the menu template field
///
public static MenuTemplate GetMenuTemplateField(string templateID, string[] menuItemTexts,
string[] menuItemDescriptions, string[] menuItemImageUrls, string[] menuItemNavigateUrls )
{
/*
*
* */
MenuTemplate menuField = new MenuTemplate();
menuField.ID = templateID;
//
//add items
for (int i = 0; i < menuItemTexts.Length; i++)
{
MenuItemTemplate itemTemplate = new MenuItemTemplate();
itemTemplate.Text = menuItemTexts[i];
itemTemplate.ID = templateID + "_item_" + i.ToString();
itemTemplate.Description = menuItemDescriptions[i];
itemTemplate.ImageUrl = menuItemImageUrls[i];
itemTemplate.Sequence = i;
itemTemplate.ClientOnClickNavigateUrl = menuItemNavigateUrls[i];
menuField.Controls.Add(itemTemplate);
}
return menuField;
}
}
[/csharp]