AjaxConnectedPageViewer
With Microsoft ASP.NET AJAX 1.0, you can build more dynamic applications that come closer to the rich style of interruption-free interaction. This web part will give a full insight of site collections as a tree view and the respective attributes as a data grid, which are connected to each other.
Introduction
This is my second release as a development cycle of an AJAX Connectable webpart. While doing some R&D, I found that the RowConsumer and Provider interfaces, ICellConsumer
and ICellProvider
are more effective when we are writing a connectable web part in the AJAX framework.
Background
This is my second article, so for a more deep insight of AJAXConnectableWebPart
, check out my previous article: AjaxConnectableWebPart_V1.0.0.0.
Using the code
First, we need to derive our web part from the ICellProvider
interface:
/// <summary>
/// This is an ajax-enabled webpart that sends
/// URL to a connectable PageViewer webpart
/// </summary>
public class AjaxUrlListWP : WebPart, ICellProvider
{
}
There are some events required by ICellProvider
:
//Events required by ICellProvider
public event CellProviderInitEventHandler CellProviderInit;
public event CellReadyEventHandler CellReady;
/// <summary>
/// This method is called by the Web Part infrastructure to notify the Web Part
/// that it has been connected.
/// </summary>
/// <param name="interfaceName">Friendly name of the interface
/// that is being connected.</param>
/// <param name="connectedPart">Reference to the other Web Part
/// that is being connected to</param>
/// <param name="connectedInterfaceName">Friendly name of the interface
/// on the other Web Part through which they are connected</param>
/// <param name="runAt">Where the interface can be executed</param>
public override void PartCommunicationConnect(string interfaceName,
WebPart connectedPart, string connectedInterfaceName, ConnectionRunAt runAt)
{
//Receive connection from "Cell_Provider_Interface_WPQ_" interface only.
if (interfaceName == "Cell_Provider_Interface_WPQ_")
{
//the connection is accepted, and the web part is connected now
isConnected = true;
}
}
/// <summary>
/// This method is called by the Web Part infrastructure to allow the Web Part
/// to fire any initialization events
/// </summary>
public override void PartCommunicationInit()
{
//if the web part is connected and the CellProviderInit listener is created,
//create the args for CellProviderInit event and fire it to tell the Consumer
//Web Part what type of cell it will be receiving when CellReady is fired later.
if (isConnected && CellProviderInit != null)
{
CellProviderInitEventArgs cellProviderInitArgs = new CellProviderInitEventArgs();
//set the field name.
cellProviderInitArgs.FieldName = "URL";
CellProviderInit(this, cellProviderInitArgs);
}
}
/// <summary>
/// This is called by the Web Part infrastructure to allow the Web Part to fire any
/// of the other events from the interface (for example, CellReady). During the
/// execution of the PartCommunicationMain method, the actual communication of data
/// values takes place between Web Parts.
/// </summary>
public override void PartCommunicationMain()
{
//if the web part is connected and CellReady event is created,
//create the args for this event and fire it.
if (isConnected && CellReady != null)
{
CellReadyEventArgs cellReadyArgs = new CellReadyEventArgs();
if (send_data && !string.IsNullOrEmpty(tv.SelectedValue))
{
//set the cell field with the selected URL
//this field will be sent to the consumer.
cellReadyArgs.Cell = tv.SelectedValue;
}
else
{
//nothing was selected
cellReadyArgs.Cell = "";
}
CellReady(this, cellReadyArgs);
}
}
/// <summary>
/// Register a client startup script to fixup the update panel, we need this
/// because Windows SharePoint Services JavaScript has a "form onSubmit wrapper"
/// which is used to override the default form action.
/// </summary>
private void EnsureUpdatePanelFixups()
{
if (this.Page.Form != null)
{
//modify the form onSubmit wrapper
if (this.Page.Form.Attributes["onsubmit"] == "return _spFormOnSubmitWrapper();")
{
this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
}
}
//register the script
ScriptManager.RegisterStartupScript(this, typeof(AjaxUrlListWP), "UpdatePanelFixup",
"_spOriginalFormAction = document.forms[0].action;" +
" _spSuppressFormOnSubmitWrapper=true;", true);
}
We are fetching the sub-sites at runtime, when the user expands the tree node. So, I have written a recursive method which will take care of filling the treeview at runtime.
public void CreateTreeOnExpandNode(string URL, TreeNode nodeExpanded)
{
try
{
SPSite site = new SPSite(URL);
SPWeb web = null;
if (site.Url == URL)
{
web = site.OpenWeb();
}
else
{
URL = URL.Replace(site.Url, "");
if (site.ServerRelativeUrl != "/") URL = site.ServerRelativeUrl + URL;
web = site.OpenWeb(URL);
}
foreach (SPWeb web1 in web.Webs)
{
TreeNode childnode = new TreeNode(web1.Url);
//GetChild(web1, childnode);
if (web1.Webs.Count > 0)
{
TreeNode emptyNode = new TreeNode();
childnode.ChildNodes.Add(emptyNode);
}
nodeExpanded.ChildNodes.Add(childnode);
}
}
catch (Exception ex)
{
Page.Response.Write(ex.Message);
}
}
Consumer part: For creating the consumer part, I have derived my control class from the ICellConsumer
interface, and the rest of the things are pretty similar to the provider part.
For getting data from the provider part:
/// <summary>
/// Implements CellReady Event Handler. Receives data from provider
/// </summary>
/// <param name="sender">provider web part</param>
/// <param name="cellReadyArgs">arguments sent by the provider</param>
public void CellReady(object sender, CellReadyEventArgs cellReadyArgs)
{
if (cellReadyArgs.Cell != null)
{
//gets the URL from the provider and save it in ContentLink
ContentLink = cellReadyArgs.Cell.ToString();
}
}
#endregion
Happy SharePointing! Cheers!!!
History
- Previous version - AJAXConnectableWebPart_V1.0.0.0.
- Current version - AJAXConnectableWebPart_V1.0.0.1.