Angeregt durch ein WebPart von René Hézser habe ich mir mal das Control SPGridView genauer angesehen. Im Gegensatz zum 'normalen' GridView wird SPGridView von SharePoint selbst verwendet, um z.B. den Inhalt von SharePoint-Listen anzuzeigen. Der große Vorteil des SPGridView: dieses Control bietet Unterstützung für Sortierung, Filterung und Paginierung - und passt sich ohne weitere Programmierung an das Layout von SharePoint an.
Im Internet finden sich einige interessante Artikel darüber, wie man eine Datenanzeige mit einem SPGridView realisieren kann. Aber jeder dieser Artikel behandelt leider immer nur einen Teilaspekt - ein umfassendes Beispiel zum Thema SPGridView habe ich nicht gefunden. Aus diesem Grund habe ich selbst das folgende Beispiel geschrieben. Es zeigt beispielhaft die Datenanzeige mit einem SPGridView mit Sortierung, Paginierung und Filterung. Leider zeigt das SPGridView beim Filtern von Spalten kein Filter-Icon an, wie man es von SharePoint-Listen kennt. Hier musste ich selbst ein wenig recherchieren - aber mit Hilfe von Greg Galipeau konnte ich auch dafür eine Lösung finden. Der Trick besteht darin, sich an das Event RowDataBound zu hängen, hier die gefilterte Spalte auszulesen und mit diesen Informationen das Filter-Icon selbst in der Kopfzeile des SPGridView in der entsprechenden Spalte anzuzeigen.
Die folgenden beiden Screenshots zeigen das SPGridView in Aktion. Im zweiten Screenshot sieht man, dass das SPGridView auch die Sortier- und Filtericons verwenden und anzeigen kann.


Bevor wir uns jetzt auch noch den Sourcecode dazu ansehen, möchte ich noch darauf hinweisen, dass der folgende Code ausschließlich als Beispiel bzw. Anschauungsobjekt gedacht ist. Er ist in der vorliegenden Form nicht dafür geeignet, unverändert in eine produktive Umgebung übernommen zu werden.
using System.Data;
using System.Reflection;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
using System.Web;
namespace Technidata.ITS.MOSS.Webparts
{
public class SPGridViewDemo : System.Web.UI.WebControls.WebParts.WebPart
{
private SPGridView m_oGridView;
private ObjectDataSource oDataSource;
public SPGridViewDemo()
{
}
protected override void CreateChildControls()
{
m_oGridView = new SPGridView();
// Set basic gridview properties
m_oGridView.ID = "MyGridView";
m_oGridView.AutoGenerateColumns = false;
m_oGridView.AlternatingRowStyle.BackColor = System.Drawing.Color.WhiteSmoke;
// Set properties for sorting
m_oGridView.AllowSorting = true;
// Set properties for paging
m_oGridView.PageSize = 3;
m_oGridView.AllowPaging = true;
m_oGridView.PagerStyle.HorizontalAlign = HorizontalAlign.Center;
// Set properties for filtering
m_oGridView.AllowFiltering = true;
m_oGridView.FilterDataFields = "Vorname,Nachname";
m_oGridView.FilteredDataSourcePropertyName = "FilterExpression";
m_oGridView.FilteredDataSourcePropertyFormat = "{1} LIKE '{0}'";
// Set EventHandler for setting the filter icon
m_oGridView.RowDataBound += new GridViewRowEventHandler(m_oGridView_RowDataBound);
// Set columns of the SPGridView
CreateGridViewColumns("Vorname");
CreateGridViewColumns("Nachname");
// Create the datasource object
oDataSource = new ObjectDataSource();
string strTypeName = "Technidata.ITS.MOSS.Webparts.SPGridViewDemo,";
strTypeName += Assembly.GetExecutingAssembly().FullName;
oDataSource.TypeName = strTypeName;
oDataSource.SelectMethod = "FillDataTable";
oDataSource.ID = "MyDataSource";
HttpRequest oRequest = HttpContext.Current.Request;
if ((oRequest.Form["__CALLBACKID"] == null) ||
(oRequest.Form["__CALLBACKPARAM"] == null) ||
(!oRequest.Form["__CALLBACKID"].EndsWith("MyGridView")))
{
if (null != ViewState["FilterExpression"])
{
oDataSource.FilterExpression = (string)ViewState"FilterExpression"];
}
}
Controls.Add(oDataSource);
// Bind SPGridView to datasource object
m_oGridView.DataSourceID = oDataSource.ID;
Controls.Add(m_oGridView);
// IMPORTANT! Call this line after Controls.Add()
m_oGridView.PagerTemplate = null;
}
// --------------------
protected override void OnPreRender(System.EventArgs e)
{
ViewState["FilterExpression"] = oDataSource.FilterExpression;
base.OnPreRender(e);
}
// --------------------
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
m_oGridView.DataBind();
base.Render(writer);
}
// --------------------
void m_oGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if ((null != sender) && (e.Row.RowType == DataControlRowType.Header))
{
string strFilteredColumn = ((SPGridView)sender).FilterFieldName;
SetGridViewFilterIcon(m_oGridView, strFilteredColumn, e.Row);
}
}
// --------------------
public void SetGridViewFilterIcon(SPGridView oGridView, string strColumn, GridViewRow oRow)
{
if ((false == string.IsNullOrEmpty(strColumn)) && (null != oRow))
{
// Show icon on filtered column
for (int iIndex = 0; iIndex < oGridView.Columns.Count; iIndex++)
{
DataControlField oField = oGridView.Columns[iIndex];
if (oField.HeaderText == strColumn)
{
Image oFilterIcon = new Image();
oFilterIcon.ImageUrl = "/_layouts/images/ewr093.gif";
oFilterIcon.ImageAlign = ImageAlign.Left;
oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginTop] = "2px";
oFilterIcon.ID = "FilterIcon";
Panel oPanel = new Panel();
oPanel.Controls.Add(oFilterIcon);
oRow.Cells[iIndex].Controls.Add(oPanel);
break;
}
}
}
}
// --------------------
public static DataTable FillDataTable()
{
DataTable oDataTable = new DataTable("Bond Actors");
DataRow row = null;
// Create the columns
oDataTable.Columns.Add("Vorname", typeof(string));
oDataTable.Columns.Add("Nachname", typeof(string));
// Fill data table
row = oDataTable.NewRow();
row["Vorname"] = "Sean";
row["Nachname"] = "Connery";
oDataTable.Rows.Add(row);
row = oDataTable.NewRow();
row["Vorname"] = "George";
row["Nachname"] = "Lazenby";
oDataTable.Rows.Add(row);
row = oDataTable.NewRow();
row["Vorname"] = "Roger";
row["Nachname"] = "Moore";
oDataTable.Rows.Add(row);
row = oDataTable.NewRow();
row["Vorname"] = "Timothy";
row["Nachname"] = "Dalton";
oDataTable.Rows.Add(row);
row = oDataTable.NewRow();
row["Vorname"] = "Pierce";
row["Nachname"] = "Brosnan";
oDataTable.Rows.Add(row);
row = oDataTable.NewRow();
row["Vorname"] = "Daniel";
row["Nachname"] = "Craig";
oDataTable.Rows.Add(row);
return oDataTable;
}
// --------------------
private void CreateGridViewColumns(string strColumn)
{
BoundField oGridColumn = new BoundField();
oGridColumn.DataField = strColumn;
oGridColumn.HeaderText = strColumn;
// IMPORTANT! This line is needed to display the arrow icons
oGridColumn.SortExpression = strColumn;
oGridColumn.Visible = true;
m_oGridView.Columns.Add(oGridColumn);
}
}
}
Nachtrag: ich bin noch auf ein kleines Problem gestossen: wenn gleichzeitig die Sortierung und die Filterung aktiviert ist und man dann die Sortierreihenfolge ändert, funktioniert das Filtern nicht mehr. Aber auch dafür findet sich eine Lösung - in diesem Fall habe ich mir ein paar Zeilen Code bei Bob's SharePoint Bonanza ausgeliehen und gleich in mein obiges Beispiel integriert. Das Prinzip ist: man sichert in den ViewStates den aktuellen Filter und setzt den Filter aus den ViewStates beim Erzeugen bzw. Parametrieren des Objekts wieder.