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:
INumberPublic Interface INumber
ReadOnly Property Number() As Integer
End Interface
NumberPickerImports SystemImports System.ComponentModelImports System.Web.UI.HtmlControlsImports System.Web.UI.WebControlsImports 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
<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
NumberDoublerImports SystemImports System.ComponentModelImports System.Web.UI.HtmlControlsImports System.Web.UI.WebControlsImports 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
Try _headerMessage = New Literal Me.Controls.Add(_headerMessage) Catch ex As Exception Me.Controls.Clear()
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
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)
<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 PropertyEnd Class
NumberTriplerImports SystemImports System.ComponentModelImports System.Web.UI.HtmlControlsImports System.Web.UI.WebControlsImports System.Web.UI.WebControls.WebParts
Public Class NumberTripler Inherits WebPart
If _numberInterface IsNot Nothing Then _number = _numberInterface.Number _result = 3 * _number End If
<ConnectionConsumer("Doubled Number", "3")> _ Public Sub AcceptNumberInterface(ByVal numberInterface As INumber) _numberInterface = numberInterface End Sub
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.