With WSS 3.0 and MOSS 2007 you can develop web parts which can be connected together as providers and consumers. WSS 3.0 and MOSS 2007 now uses the .NET 2.0 connectable web part technology. This sample demonstrates a consumer webpart which will consume row data provided by OOTB web parts using the standard IWebPartRow interface. Custom developed web parts can implement their own connection interfaces of course, but the advantage of using the standard interfaces is that they can be integrated with the OOTB ones.
The IWebPartRow interface provides access to a row of data provided by the provider web part. Using the OOTB List View Webpart (the standard webparts which represent standard and custom lists / document libraries) as an example provider, these web parts view list data using one of the views attached to the list (and you can customise the web parts copy of that view also). So in terms of a row of data, a provider such as this will offer the currently selected row in the providers view. The contents of this row (i.e the columns) are the list columns selected for display in the web parts view. If the list is a Document or Form library their will also be a column called DocuUrl, which is the site relative url of the Document/Form library items SPFile. If the list is just a list, their will also be a column called Attachments.
Changing the columns displayed on the provider web parts view, then, obviously changes the data row columns offered to consumers.
As far as web part life cycle events go, things follow the normal web part life cycle model (see this post), however, the call to SetConnectionInterface() follows OnLoad(). This call connects the 2 web parts, but no data has been transferred as yet. It turns out that the data transfer action follows a pull model (from the consumers point of view) and it is the consumers resonsibility to pull the data from the provider as and when ready.
The consumer can pull the data from the provider whenever they require, except that it can obviously only be done after the SetConnectionInterface() method has been called. To retrieve the data, the consumer makes a call to _provider.GetRowData(callback_method). The callback_method is implemented in the consumer code, the single parameter to this callback method represents the row data and must be cast to the required type. Note, that the provider calls the consumers callback_method synchronously.
The consumer web part developed here will be connected to a Document library list view provider shown below, note the columns displayed on the view.
When connected to this provider web part, the consumer displays as follows.
The code for the consumer web part is show here.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Data;
using Microsoft.SharePoint;
namespace MbosSampleWebParts
{
[Guid("4517a282-9681-4f7c-ac9f-b12fb200ab07")]
public class MbosViewerWebPart : WebPart
{
private DataRowView _dataRow;
private IWebPartRow _provider;
private readonly StringBuilder _sb = new StringBuilder();
public MbosViewerWebPart()
{
_sb.Append("- Ctor\n");
PreRender += MbosViewerWebPart_PreRender;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_sb.Append(state("OnLoad"));
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
_sb.Append(state("OnInit"));
}
void MbosViewerWebPart_PreRender(object sender, EventArgs e)
{
_sb.Append(state("PreRender.1"));
// if (_provider != null)
// _provider.GetRowData(GetRowData);
_sb.Append(state("PreRender.2"));
}
protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(writer);
_sb.Append(state("RenderContents"));
if (_provider != null)
{
try
{
PropertyDescriptorCollection schemaProps = _provider.Schema;
if (schemaProps != null && schemaProps.Count > 0 && _dataRow != null)
{
DataRow providerRow = _dataRow.Row;
// enumerate data columns
_sb.Append("\n");
foreach (DataColumn column in providerRow.Table.Columns)
_sb.AppendFormat("- data column: {0} = {1}\n", column.ColumnName ?? "n/a", providerRow[column]);
// enumerate schema
_sb.Append("\n");
foreach (PropertyDescriptor prop in schemaProps)
_sb.AppendFormat("- schema entry: {0} is {1}\n", prop.Name, prop.PropertyType);
try
{
// get the SPFile of the connected item (if doc/form library item)
var colDocUrl = providerRow.Table.Columns["DocUrl"];
if (colDocUrl != null)
{
var connectedFile = SPContext.Current.Web.GetFile(providerRow[colDocUrl].ToString());
_sb.AppendFormat("\n- SPFile.Author.Name: {0}\n", connectedFile.Author.Name);
}
}
catch (Exception e)
{ _sb.Append(e.Message + "\n"); }
}
else
_sb.Append(" - No data\n");
}
catch (Exception ex)
{ _sb.Append(ex.Message +"\n"); }
}
else
_sb.Append("- Not connected\n");
writer.Write(_sb.ToString().Replace("\n", "< br >")); // replace LF with HTML line-break
}
protected override void Render(HtmlTextWriter writer)
{
_sb.Append(state("Render"));
base.Render(writer);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
_sb.Append(state("CreateChildControls.1"));
if (_provider != null)
_provider.GetRowData(GetRowData);
_sb.Append(state("CreateChildControls.2"));
}
private string state(string method)
{
var sb = new StringBuilder();
sb.AppendFormat("- {0}", method);
if (_provider != null)
sb.Append(", _provider not null");
else
sb.Append(", _provider null");
if (_dataRow != null)
sb.Append(", _dataRow not null");
else
sb.Append(", _dataRow null");
sb.Append("\n");
return sb.ToString();
}
private void GetRowData(object rowData)
{
_sb.Append(state("GetRowData.1"));
try
{
_dataRow = (DataRowView)rowData;
}
catch
{ _dataRow = null; }
_sb.Append(state("GetRowData.2"));
}
[ConnectionConsumer("Row")]
public void SetConnectionInterface(IWebPartRow provider)
{
_provider = provider;
_sb.Append(state("SetConnectionInterface"));
}
}
}


RSS - Posts
My