Web Part Connections in WSS 3.0
Josh Holmes recently asked me to present a couple of small demos for an ArcReady event in Memphis. While looking through my material, I discovered a couple of web parts that I had written a while ago. I wrote these web parts in order to investigate how to send data from one part to another. They illustrate how easy it is to set up Web Part Connections in WSS 3.0, so I thought I'd share them here.
In this post, I'll show how to send data from one web part to another. Later posts will demonstrate how one web part can provide data to multiple web parts, how one web part can consume data from multiple parts, and how a web part can be a provider and a consumer at the same time. As you will see, with WSS 3.0, this is very easy to do.
Now, programs need a purpose, and web parts are no different. These web parts provide different types of information about the Towers of Hanoi puzzle. In this post, I'll use two web parts. One web part contains a drop-down list that can be used to specify the number of disks used for the puzzle. The second web part contains a list box that enumerates the steps needed to solve the puzzle with the number of disks specified in the first web part. For this to work properly, the second web part must obtain data from the first web part. So, how does this work?
First, data is exchanged via interfaces. In this case, the interface is called IDisks:
IDisks.vb
Public Interface IDisks
ReadOnly Property NumberOfDisks() As Integer
End Interface
This interface will be used to pass the selected number of disks from one web part to the other.
The first web part will allow the user to select the number of disks that should be used for the puzzle. It is called HanoiDisks:
HanoiDisks.vb
Imports System
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebPartsPublic Class HanoiDisks
Inherits WebPart
Implements IDisksProtected diskList As DropDownList = Nothing
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()Dim t As Table = Nothing
Dim tr As TableRow = Nothing
Dim td As TableCell = NothingTry
diskList = New DropDownListWith diskList
.AutoPostBack = True.Items.Clear()
.Items.Add(New ListItem("Three", 3))
.Items.Add(New ListItem("Four", 4))
.Items.Add(New ListItem("Five", 5))
.Items.Add(New ListItem("Six", 6))
.Items.Add(New ListItem("Seven", 7))
.Items.Add(New ListItem("Eight", 8)).SelectedIndex = 0
End Witht = New Table
tr = New TableRowtd = New TableCell
td.Text = "Number of Disks: "
tr.Controls.Add(td)td = New TableCell
td.Controls.Add(diskList)
tr.Controls.Add(td)t.Controls.Add(tr)
Me.Controls.Add(t)
Catch ex As Exception
Me.Controls.Clear()Dim msg As New Literal()
msg.Text = ex.Message
Me.Controls.Add(msg)
End TryEnd Sub
<ConnectionProvider("Number of Disks")> _
Public Function GetDiskInterface() As IDisks
Return Me
End FunctionPublic ReadOnly Property NumberOfDisks() As Integer Implements IDisks.NumberOfDisks
Get
Return diskList.SelectedValue
End Get
End PropertyEnd Class
Notice that HanoiDisks inherits from WebPart. This is the standard .NET 2.0 WebPart class, and it performs most of the work for us. All we have to do is override CreateChildControls to add our UI. The HanoiDisks class also implements the IDisks interface that was mentioned earlier. It returns the value of the selected item in the dropdown list in our UI.
The GetDiskInterface method is the key to the web part communication. It returns the HanoiDisks class as an instance of the IDisks interface. It uses the ConnectionProvider attribute to inform WSS that this method provides data for another web part. WSS does the rest.
Now let's look at the HanoiSteps web part, which lists the steps needed to solve the puzzle.
HanoiSteps.vb
Imports System
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebPartsPublic Class HanoiSteps
Inherits WebPartProtected _diskInterface As IDisks = Nothing
Protected _disks As Integer = 0
Protected _stepList As ListBox = Nothing
Protected _headerMessage As Literal = NothingProtected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()Try
_headerMessage = New Literal
Me.Controls.Add(_headerMessage)Dim br As New HtmlGenericControl("br")
Me.Controls.Add(br)_stepList = New ListBox
With _stepList
.SelectionMode = ListSelectionMode.Single
.Rows = 7
End WithMe.Controls.Add(_stepList)
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 IfEnd Sub
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
If _headerMessage IsNot Nothing Then
_headerMessage.Text = "Here are the steps for " & _disks & " disks:"
End IfIf _stepList IsNot Nothing AndAlso _disks > 1 Then
FillListWithSteps(_stepList, _disks)
End IfMyBase.RenderContents(writer)
End Sub
<ConnectionConsumer("Number of Disks")> _
Public Sub AcceptDiskInterface(ByVal diskInterface As IDisks)
_diskInterface = diskInterface
End SubPrivate Sub FillListWithSteps(ByVal list As ListBox, ByVal disks As Integer)
list.Items.Clear()
Towers(list, disks, 1, 3, 2)
End Sub
Private Sub Towers(ByVal list As ListBox, ByVal disks As Integer, ByVal fromPole As Integer, ByVal toPole As Integer, ByVal usingPole As Integer)
If disks = 1 Then
list.Items.Add(String.Format("Move a disk from pole {0} to pole {1}", fromPole, toPole))
Else
Towers(list, disks - 1, fromPole, usingPole, toPole)
Towers(list, 1, fromPole, toPole, usingPole)
Towers(list, disks - 1, usingPole, toPole, fromPole)
End IfEnd Sub
End Class
Most of this code is needed just to make this web part work. That is, to create UI controls that list the steps needed to solve the puzzle. The AcceptDiskInterface method is the key to accepting data from the first web part. It accepts an instance of the IDisks interface and stores it for later use. The ConnectionConsumer attribute is used to tell WSS that this method will consume data. The OnPreRender method checks to see if the interface has been received. If so, it stores the number of disks in a variable. The RenderContents method uses this variable to determine how many disks have been specified, and what steps are needed to solve the puzzle.
All that's left is to edit one of the web parts, select the connections menu, and link the parts together.
This completes the first post. We've seen how one web part can pass data to another. Look for another post soon, where I'll expand on this topic.
Note that, while you are free to use this code as you wish, it comes with no guarantees. I wrote it simply for illustration purposes, not for actual use.
Comments
Anonymous
September 01, 2007
In part 1 of this series, I showed how to make one web part accept data from another. In this part, I'llAnonymous
September 01, 2007
In part 1 of this series, I showed how to make one web part accept data from another. In this part, I'llAnonymous
September 02, 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 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
March 06, 2008
The comment has been removedAnonymous
July 29, 2008
I got the link to this article from Darren about the web part connection problem. It really helps , many many thanks.