Web Part Connections in WSS 3.0 (Part 4)
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. In part 3, which I thought was going to be the last part, I showed how a single web part can accept data from multiple web parts. Now, in the fourth part of my three-part series, I'm going to show how data can be passed from one web part to another in a sort of chain.
I have three web parts; NumberPicker, NumberDoubler, and NumberTripler. I want the data to flow like this:
NumberPicker --> NumberDoubler --> NumberTripler
The user will use NumberPicker to select a number from one to five. This number is passed to NumberDoubler, which doubles the number and displays it. This doubled number is then passed to NumberTripler, which triples the number and displays the final result. The important point here is that data is received from one part and provided to the next, and specifically that the data provided depends upon the data recieved. Here's the code that I used:
INumber
Public Interface INumber
ReadOnly Property Number() As Integer
End Interface
NumberPicker
Imports System
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Public Class NumberPicker
Inherits WebPart
Implements INumber
Private _NumberList As DropDownList
Public Sub New()
Me.ExportMode = WebPartExportMode.All
End Sub
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()
Dim t As Table = Nothing
Dim tr As TableRow = Nothing
Dim td As TableCell = Nothing
Try
_NumberList = New DropDownList
With _NumberList
.AutoPostBack = True
.Items.Clear()
.Items.Add(New ListItem("One", 1))
.Items.Add(New ListItem("Two", 2))
.Items.Add(New ListItem("Three", 3))
.Items.Add(New ListItem("Four", 4))
.Items.Add(New ListItem("Five", 5))
.SelectedIndex = 0
End With
t = New Table
tr = New TableRow
td = New TableCell
td.Text = "Number: "
tr.Controls.Add(td)
td = New TableCell
td.Controls.Add(_NumberList)
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 Try
End Sub
<ConnectionProvider("Selected Number")> _
Public Function GetNumberInterface() As INumber
Return Me
End Function
Public ReadOnly Property Number() As Integer Implements INumber.Number
Get
Return _NumberList.SelectedValue
End Get
End Property
End Class
NumberDoubler
Imports System
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Public Class NumberDoubler
Inherits WebPart
Implements INumber
Protected _numberInterface As INumber = Nothing
Protected _number As Integer = 0
Protected _result As Integer = 0
Protected _headerMessage As Literal = Nothing
Public Sub New()
Me.ExportMode = WebPartExportMode.All
End Sub
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 Try
End Sub
Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
MyBase.OnPreRender(e)
If _numberInterface IsNot Nothing Then
_number = _numberInterface.Number
_result = 2 * _number
End If
End Sub
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
If _headerMessage IsNot Nothing AndAlso _number > 0 Then
_headerMessage.Text = _result
End If
MyBase.RenderContents(writer)
End Sub
<ConnectionConsumer("Selected Number", "1")> _
Public Sub AcceptNumberInterface(ByVal numberInterface As INumber)
_numberInterface = numberInterface
End Sub
<ConnectionProvider("Doubled Number", "2")> _
Public Function GetNumberInterface() As INumber
Return Me
End Function
Public ReadOnly Property Number() As Integer Implements INumber.Number
Get
Return _result
End Get
End Property
End Class
NumberTripler
Imports System
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Public Class NumberTripler
Inherits WebPart
Protected _numberInterface As INumber = Nothing
Protected _number As Integer = 0
Protected _result As Integer = 0
Protected _headerMessage As Literal = Nothing
Public Sub New()
Me.ExportMode = WebPartExportMode.All
End Sub
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 Try
End Sub
Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
MyBase.OnPreRender(e)
If _numberInterface IsNot Nothing Then
_number = _numberInterface.Number
_result = 3 * _number
End If
End Sub
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
If _headerMessage IsNot Nothing AndAlso _number > 0 Then
_headerMessage.Text = _result
End If
MyBase.RenderContents(writer)
End Sub
<ConnectionConsumer("Doubled Number", "3")> _
Public Sub AcceptNumberInterface(ByVal numberInterface As INumber)
_numberInterface = numberInterface
End Sub
End Class
The real trick here is that the numbers are calculated during the OnPreRender event. We have to wait long enough to ensure that the NumberPicker web part has created its internal controls, which is where the original data resides. We also need to act early enough to allow the data to be passed along from part to part. If you are not careful, one of the web parts may be rendered before the data has been passed to it.
I hope this helps.
Comments
Anonymous
November 08, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/11/08/web-part-connections-in-wss-30-part-4/Anonymous
December 11, 2007
The comment has been removed