Web Part Connections in WSS 3.0 (Part 3)
In part 1 of this series, I showed how to make one web part accept data from another. In part 2, I showed that this can be extended so that one web part can provide data for many. Now, in this final post of the series, I'll show how a single web part can accept data from multiple web parts. As you will see, we need to make only a few changes for this to happen.
Let's continue from where we left off. Our page now has three web parts. The first, HanoiDisks, allows the user to select the number of disks that should be used for our Towers of Hanoi puzzle. The second web part, HanoiSteps, displays the steps needed to solve the puzzle. The third web part, HanoiCount, displays the number of steps that will be needed to complete the puzzle. Now we'll add a fourth web part. This web part, HanoiColor, will allow the user to select the font color used by the HanoiCount web part. HanoiCount will then be using data from both the the HanoiColor and the HanoiDisk web parts.
So far, we've been passing around instances of the IDisks interface. We're now going to pass color information, so we need a new interface:
IColor.cb
Public Interface IColor
ReadOnly Property Color() As Integer
End Interface
This interface will allow a color number to be passed from HanoiColor to HanoiCount. First, lets look at the new HanoiColor web part:
HanoiColor.vb
Imports System
Imports System.Drawing
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebPartsPublic Class HanoiColor
Inherits WebPart
Implements IColorProtected _colorList As DropDownList = Nothing
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()Try
_colorList = New DropDownListWith _colorList
.AutoPostBack = True.Items.Clear()
.Items.Add(New ListItem("Black", 0))
.Items.Add(New ListItem("Blue", 1))
.Items.Add(New ListItem("Green", 2))
.Items.Add(New ListItem("Red", 3)).SelectedIndex = 0
End WithDim lit As New Literal()
lit.Text = "Text Color: "
Me.Controls.Add(lit)Me.Controls.Add(_colorList)
Catch ex As Exception
Me.Controls.Clear()Dim msg As New Literal()
msg.Text = ex.Message
Me.Controls.Add(msg)
End TryEnd Sub
<ConnectionProvider("Text Color")> _
Public Function GetColorInterface() As IColor
Return Me
End FunctionPublic ReadOnly Property Color() As Integer Implements IColor.Color
Get
Return _colorList.SelectedValue
End Get
End Property
End Class
By now, you should recognize all of the features of this code. The GetColorInterface method provides an instance of the IColor interface, and uses the ConnectionProvider attribute to communicate this fact to WSS.
Now, let's look at the HanoiCount web part. It now needs to accept data from two different sources, so some code changes are needed:
HanoiCount.vb
Imports System
Imports System.Drawing
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebPartsPublic Class HanoiCount
Inherits WebPartProtected _diskInterface As IDisks = Nothing
Protected _disks As Integer = 0Protected _colorInterface As IColor = Nothing
Protected _color As String = "#000000;"Protected _headerMessage As Literal = Nothing
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()Try
_headerMessage = New Literal
Me.Controls.Add(_headerMessage)
Catch ex As Exception
Me.Controls.Clear()Dim msg As New Literal()
msg.Text = ex.Message
Me.Controls.Add(msg)
End TryEnd Sub
Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
MyBase.OnPreRender(e)If _diskInterface IsNot Nothing Then
_disks = _diskInterface.NumberOfDisks
End IfIf _colorInterface IsNot Nothing Then
_color = GetColorFromNumber(_colorInterface.Color)
End IfEnd Sub
Private Function GetColorFromNumber(ByVal colorNumber As Integer) As String
Dim selectedColor As String = "#000000;"
Select Case colorNumber
Case 0
selectedColor = "#000000;"
Case 1
selectedColor = "#0000FF;"
Case 2
selectedColor = "#00FF00;"
Case 3
selectedColor = "#FF0000;"
End SelectReturn selectedColor
End Function
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
If _headerMessage IsNot Nothing AndAlso _disks > 1 Then
Dim steps As Integer = 2 ^ _disks - 1
With _headerMessage
.Text = "<span style=""color:" & _color & """>"
.Text &= "There are " & steps & " steps for " & _disks & " disks."
.Text &= "</span>"
End With
End IfMyBase.RenderContents(writer)
End Sub
<ConnectionConsumer("Number of Disks", "1")> _
Public Sub AcceptDiskInterface(ByVal diskInterface As IDisks)
_diskInterface = diskInterface
End Sub<ConnectionConsumer("Text Color", "2")> _
Public Sub AcceptColorInterface(ByVal colorInterface As IColor)
_colorInterface = colorInterface
End SubEnd Class
Notice that two interfaces are used here. This fact is reflected throughout most of the code. Also notice that there are two methods that accept interfaces; AcceptDiskInterface and AcceptColorInterface. Look closely at the ConnectionConsumer attributes. Up until now, I've supplied only one parameter to the attribute constructor. This works just fine when there is only one ConnectionConsumer or ConnectionProvider attribute used by a web part. When you have more than one, however, you need to also supply a unique identifier for each attribute. This is the real trick to using multiple web part connections.
At this point, we've written four web parts that communicate with each other in various ways:
- HanoiCount - provides an instance of the IColor interface to the HanoiCount web part
- HanoiDisks - provides an instance of the IDisks interface to the HanoiCount and HanoiSteps web parts
- HanoiCount - accepts an instance of the IColor interface from the HanoiColor web part, and an instance of the IDisks interface from the HanoiDisks web part
- HanoiSteps - accepts an instance of the IDisks interface from the HanoiDisks web part
I leave it to the reader to create a final web part; one that is both a provider and a consumer of data. The can be accomplished by using the same techniques presented in this series of posts.
I hope these posts have helped you get started with web part communication. This can be a very useful feature of WSS 3.0.
Comments
Anonymous
September 02, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/09/02/web-part-connections-in-wss-30-part-3/Anonymous
September 03, 2007
PingBack from http://stevepietrekweblog.wordpress.com/2007/09/03/links-932007/Anonymous
October 29, 2007
Hi Jerbear, Your article is very useful, but I'd like to see the code for web part that behaves as provider and consumer at the same time. If it's not possible to do such a thing, please, point us to right direction and tips related to this thing. Thank you in advace. GoranAnonymous
October 29, 2007
The comment has been removedAnonymous
November 05, 2007
The comment has been removedAnonymous
November 08, 2007
Hi Goran, I think you may have explained your situation incorrectly. You mentioned that P2 and P3 both connect to P1. I demonstrate how to do that in Part 2 of my series. (HanoiDisks provides the number of disks selected to HanoiCount and HanoiSteps.) However, I believe that you meant to describe this: P1->P2->P3. Am I correct?Anonymous
November 08, 2007
In part 1 of this series, I showed how to make one web part accept data from another. In part 2 , I showedAnonymous
November 08, 2007
In part 1 of this series, I showed how to make one web part accept data from another. In part 2 , I showedAnonymous
November 20, 2007
The comment has been removedAnonymous
November 20, 2007
The comment has been removedAnonymous
November 21, 2007
The comment has been removed