Recently some co-workers have complained that there are no working/good examples on the web of how to create web parts that can be connected, so I created an example with the entire source included so you can have a "working" example. The only thing left off here are the include statements, but since this is all simple .NET the includes are easy to recreate.
For this example we will create two web parts and, once added to the SharePoint page, connect the web parts. Web part connects follow the Provider-Consumer design concept, the advantage is that multiple consumers can connect to a single provider and each can work independently on the information provided.
An important consideration when developing connected web parts is that once the connection is specified every time the page is loaded, initial access/postback/etc, all cause the provider interface implementation to be passed to the consumer and the consumer will attempt to access the values. Therefore it is very important to provide some default values to be provided.
Connection Contract
The connection contract is established through the use of an Interface object. This object will define what the consumer can request from its provider, and what the provider must implement . For this example we want to pass a text string from the provider to the consumer for display, therefore our interface will simply provide the consumer the ability to "get" the string.
IConnectionInterface.cs
namespace ConnectedControls
{
public interface IConnectionInterface
{
string GetProviderString();
}
}
Provider Web Part
The ProviderControl class will serve as the web part that provides the information to one or many consumers. This web part implements the Connection Contract Interface as well as inheriting from the WebPart class.
namespace ConnectedControls
{
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ProviderControl : WebPart, IConnectionInterface
{
…
#region IConnectionInterface Members
private string _textBoxValue;
public string GetProviderString()
{
return _textBoxValue;
}
#endregion
}
}
This class must also provide a method for the .NET architecture to access it's interface implementation. This is done by defining a method that returns the Interface type as well as defining its Connection Provider Attributes.
//Establish Web Part Connection Point for the consumer
[ConnectionProvider("Provider Connection", AllowsMultipleConnections=true)]
public IConnectionInterface GetTextCommunicationPoint()
{
return this as IConnectionInterface;
}
The [ConnectionProvider(…)] tells the .NET architecture that this function is used to provide data to consumer web parts. The .NET Framework will leverage this function to get a handle to the Connection Contract Interface so it can be provided to the consumer object.
Finally, we need to allow the user to enter some text and cause a callback to occur so that our connected parts can pass information. Here we override the CreateChildControl so we can create a TextBox and a Button for text input and callback events.
protected override void CreateChildControls()
{
Label lbl = new Label();
_tbControl = new TextBox();
Button btnSubmit = new Button();
lbl.Text = "Enter text to send to the connected webpart";
Controls.Add(lbl);
Controls.Add(_tbControl);
btnSubmit.Click += new EventHandler(SetTextBoxString);
btnSubmit.Text = "Submit";
Controls.Add(btnSubmit);
}
void SetTextBoxString(object sender, EventArgs e)
{
_textBoxValue = _tbControl.Text;
}
ProviderControl.cs
namespace ConnectedControls
{
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ProviderControl : WebPart, IConnectionInterface
{
TextBox _tbControl;
string _textBoxValue;
//Establish Web Part Connection Point for the consumer
[ConnectionProvider("Provider Connection", AllowsMultipleConnections=true)]
public IConnectionInterface GetTextCommunicationPoint()
{
return this as IConnectionInterface;
}
protected override void CreateChildControls()
{
Label lbl = new Label();
_tbControl = new TextBox();
Button btnSubmit = new Button();
lbl.Text = "Enter text to send to the connected webpart";
Controls.Add(lbl);
Controls.Add(_tbControl);
btnSubmit.Click += new EventHandler(SetTextBoxString);
btnSubmit.Text = "Submit";
Controls.Add(btnSubmit);
}
void SetTextBoxString(object sender, EventArgs e)
{
_textBoxValue = _tbControl.Text;
}
#region IConnectionInterface Members
public string GetProviderString()
{
return _textBoxValue;
}
#endregion
}
}
Consumer Web Part
The consumer web part will leverage the connection and the interface to retrieve information from the provider. In order to get access to the Provider's impleneted interface the consumer must define a method that will receive the interface as a parameter and mark the method as a ConnectionConsumer.
[ConnectionConsumer("Connection Consumer")]
public void InitializeConnection(IConnectionInterface connectionInterface)
{
_connectedPartText = connectionInterface.GetProviderString();
}
By adding the [ConnectionConsumer(…)] the .NET Framework recognizes this function as being capable of consuming connections and, when connected, will provide the method with a handle to the provider object's implemented Connection Contract Interface.
Now all that is left is to display the provider's information, and to do this we simply override the RenderContents method in our Consumer web part.
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("<b>Text from connected web part:</b><i>" + _connectedPartText + "</i><br/>");
}
ConsumerControl.cs
namespace ConnectedControls
{
[ToolboxData("<{0}:ConsumerControl runat=server></{0}:ConsumerControl>")]
public class ConsumerControl : WebPart
{
string _connectedPartText;
[ConnectionConsumer("Connection Consumer")]
public void InitializeConnection(IConnectionInterface connectionInterface)
{
_connectedPartText = connectionInterface.GetProviderString();
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("<b>Text from connected web part:</b><i>" + _connectedPartText + "</i><br/>");
}
}
}
Web part connections to NOT require any specialized security settings, therefore you can deploy these web parts to the bin.