«

»

Automatically connect WebParts on a SharePoint page

For a recent project we had several WebParts (Provider and Consumer webparts) on a page which had to be connected to each other when the page was provisioned by our solution.

Unfortunately this cannot be done within the Module.xml :(

So I created a method which automatically connects the consumer WebParts to their correct provider WebParts.

To do this I basically used the SPLimitedWebPartManager, ProviderConnectionPoint, ConsumerConnectionPoint and some other nice classes.

The method (warning long block of code)

/// <summary>
/// Connects the web parts on page.
/// </summary>
/// <param name="web">The web.</param>
/// <param name="pageUrl">The page URL.</param>
/// <param name="publish">if set to <c>true</c> [publish].</param>
public static void ConnectWebPartsOnPage(SPWeb web, string pageUrl, bool publish)
{
	// get the page from the url
	SPFile page = web.GetFile(pageUrl);

	// make sure the page exists
	if (page.Exists)
	{
		// if the page is checked out, check it in because then the user can do an rollback
		if (page.Level == SPFileLevel.Checkout)
		{
			page.CheckIn("Page was checked out, needs to be checked in before connecting webparts", SPCheckinType.MinorCheckIn);
		}

		// check out the page because we are going to do changes on it
		page.CheckOut();

		// get the webpartmanager for the page
		using (Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager mgr = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
		{
			try
			{
				// try to connect the webparts on the page
				if (ConnectWebParts(mgr))
				{
					string checkinComment = "Auto connected WebParts on page";

					// webparts are connected so update the page and check it in
					page.Update();
					page.CheckIn(checkinComment);

					if (publish)
					{
						page.Publish(checkinComment);
						page.Approve(checkinComment);
					}
				}
			}
			catch (Exception ex)
			{
				page.UndoCheckOut();
				throw ex;
			}
		}
	}
}

/// <summary>
/// Checks if a WebPart connection exists.
/// </summary>
/// <param name="connections">The connections.</param>
/// <param name="provider">The provider.</param>
/// <param name="consumer">The consumer.</param>
/// <returns></returns>
private static bool WebPartConnectionExist(Microsoft.SharePoint.WebPartPages.SPWebPartConnectionCollection connections,
	System.Web.UI.WebControls.WebParts.WebPart provider, System.Web.UI.WebControls.WebParts.WebPart consumer)
{
	foreach (Microsoft.SharePoint.WebPartPages.SPWebPartConnection conn in connections)
	{
		if (conn.Provider == provider && conn.Consumer == consumer)
		{
			return true;
		}
	}

	return false;
}

/// <summary>
/// Connects the web parts.
/// </summary>
/// <param name="manager">The manager.</param>
/// <returns></returns>
private static bool ConnectWebParts(Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager manager)
{
	bool connectionMade = false;

	// get the webparts on the page
	Microsoft.SharePoint.WebPartPages.SPLimitedWebPartCollection webparts = manager.WebParts;

	// only continu if there are any webparts
	if (webparts.Count > 0)
	{
		ProviderConnectionPointCollection provColl;
		ConsumerConnectionPointCollection consColl;
		// walk through all the webparts on the page to find provider webparts
		foreach (System.Web.UI.WebControls.WebParts.WebPart providerPart in webparts)
		{

			// check if the webpart is a Provider webpart
			provColl = manager.GetProviderConnectionPoints(providerPart);
			if (provColl != null && provColl.Default != null)
			{

				// walk through all the webparts on the page again now to find the consumer webparts
				foreach (System.Web.UI.WebControls.WebParts.WebPart consumerPart in webparts)
				{

					// first make sure the webpart isn't the provider webpart
					if (consumerPart != providerPart)
					{
						// check if the webpart is a Consumer webpart,
						// then make sure the consumer webpart isn't already connected to the provider webpart
						// then check if the interface of the consumer webpart is assignable from the interface of the provider webpart
						consColl = manager.GetConsumerConnectionPoints(consumerPart);
						if (consColl != null && consColl.Default != null
							&& !WebPartConnectionExist(manager.SPWebPartConnections, providerPart, consumerPart)
							&& consColl.Default.InterfaceType.IsAssignableFrom(provColl.Default.InterfaceType))
						{
							// connect the webparts
							manager.SPConnectWebParts(providerPart, provColl.Default, consumerPart, consColl.Default);
							connectionMade = true;
						}
					}
				}
			}
		}
	}
	return connectionMade;
}

Sample usage (console application)

try
{
	using (SPSite site = new SPSite("http://localhost"))
	using (SPWeb web = site.OpenWeb())
	{
		ConnectWebPartsOnPage(web, "pages/default.aspx", false);
	}
}
catch (Exception ex)
{
	Console.WriteLine();
	Console.WriteLine("Message:\n{0}\n\nStack:\n{1}\n\n", ex.Message, ex.StackTrace);
}

5 comments

  1. Deepti says:

    Great post !!

    But for me “provColl.Default” & “consColl.Default” are coming null. Both are visual webparts and using User controls.

    Any Idea what is going wrong ??

  2. Deepti says:

    @Deepti

    I found the way :)

  3. ThumNet says:

    Could you please supply the solution so I can update the blogpost?

  4. Heart attack vioxx says:

    For a recent project we had several WebParts (Provider and Consumer webparts) on a page which had to be connected to each other when the page was provisioned by our solution.
    +1

  5. ThumNet says:

    @Heart attack vioxx
    Glad to have helped!

    I think you made a little typo “provisioned by our solution” should be “provisioned by your solution” ;)

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>