Another ASP.NET WebParts Connections Sample
July 2004
Summary:
This article shows another sample of using WebParts.
In this case we will create two WebParts:
- Author WebPart that displays the list of authors in the database.
- Books WebPart that displays the list of books in the database.
Both WebParts are completely independent from each other.
However when a user chooses to connect them, the Authors WebPart provides an IField interface to the Books webpart that is used to filter the books so only the ones from the selected author will be displayed.
We will also show other features of WebParts to illustrate how a user can add WebParts to his page that are only available through the Catalog not already in the page.
Visits:58
Lets first show the code.
To run this sample you have to create a new WebSite in Visual Web Developer Express
or use Visual Studio .NET 2005 (or just create a virtual directory in IIS).
The Page
Lets start by showing how simple the page is:
Save the following code in a file with the extension .ASPX:
<%@ Page Language="C#" %> <%@ Register TagPrefix="my" Namespace="MyWebParts" %> <html> <head runat="server"> <title>WebParts Sample</title> </head> <body> <form id="form1" runat="server"> <asp:WebPartManager runat="server" ID="WPM" /> <asp:WebPartPageMenu runat="server" ID="WPPM" /> <asp:WebPartZone runat="server" ID="Zone1"
/> <asp:ConnectionsZone runat="server" ID="connectionsZone1" /> <asp:CatalogZone runat="server" ID="catalogZone1"> <ZoneTemplate> <asp:DeclarativeCatalogPart runat="server" ID="declarative1"> <WebPartsTemplate> <my:AuthorWebPart runat="server" ID="author1" Title="Authors" /> <my:BooksWebPart runat="server" ID="books1" Title="Books" /> </WebPartsTemplate> </asp:DeclarativeCatalogPart> <asp:PageCatalogPart runat="Server" ID="pageCatalog1" /> </ZoneTemplate> </asp:CatalogZone> </form> </body> </html>
The first thing to notice is that we are not adding any WebPart to the WebPartZone,
the WebParts are only "declared" to be available using a CatalogZone, in this case
we are using the DeclarativeCatalogPart that allows to define a set of WebParts
that are available for the user.
We also added to the page a WebPartPageMenu that will allow us to move between the
different display modes of WebParts.
The WebParts
Save the following code into a file named MyWebParts.cs or MyWebParts.vb and save it inside a Code
directory inside the virtual directory.
C# Code
namespace MyWebParts { using System; using System.Drawing;
using System.ComponentModel;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
/// <summary> /// WebPart to display the information of Authors
/// </summary> public class AuthorWebPart : WebPart, IField {
GridView _view;
public AuthorWebPart() {
}
protected override void CreateChildControls() {
_view = new GridView(); _view.ID = "_authorsGrid"; _view.AutoGenerateColumns = true;
_view.DataKeyNames = new string[] { "au_id" }; CommandField field = new CommandField(); _view.SelectedRowStyle.BackColor = Color.Red; field.ShowSelectButton = true; _view.Columns.Add(field);
SqlDataSource ds = new SqlDataSource(); ds.ID = "_authorsDS"; ds.ConnectionString = "server=carlosagmail;database=pubs;uid=sa;pwd=yourpassword";
ds.SelectCommand = "select au_id, au_lname, au_fname from authors"; _view.DataSourceID = ds.ID;
this.Controls.Add(ds); this.Controls.Add(_view); }
[ConnectionProvider("AuthorID")] public IField GetAuthor() {
return this; }
#region IField Members object IField.FieldValue {
get { return _view.SelectedValue; } } PropertyDescriptor IField.Schema { get { return TypeDescriptor.GetProperties(this.GetType())["FieldValue"]; } } #endregion
}
/// <summary>
/// WebPart to display the information
of Books
/// </summary> public class BooksWebPart : WebPart { private IField _authorField;
SqlDataSource _ds;
[ConnectionConsumer("Author")]
public void SetAuthor(IField field) { this._authorField = field; }
protected override void CreateChildControls() { GridView view = new GridView(); view.ID = "_booksGrid";
view.AutoGenerateColumns = true; view.DataKeyNames = new string[] { "title_id" }; CommandField field = new CommandField(); view.SelectedRowStyle.BackColor = Color.Red; field.ShowSelectButton = true;
view.Columns.Add(field);
_ds = new SqlDataSource(); _ds.ID = "_booksDS";
_ds.ConnectionString = "server=carlosagmail;database=pubs;uid=sa;pwd=yourpassword"; view.DataSourceID = _ds.ID;
this.Controls.Add(_ds); this.Controls.Add(view); }
protected override void OnPreRender(EventArgs e) { const string selectStatement = "SELECT titles.title_id, titles.title, titles.type, titles.price, titles.pubdate FROM titles";
EnsureChildControls(); if (_authorField != null) { if (_ds.SelectParameters.Count == 0) {
_ds.SelectCommand = selectStatement + " INNER JOIN titleauthor ON titleauthor.title_id = titles.title_id WHERE (titleauthor.au_id = @au_id)"; _ds.SelectParameters.Add(new Parameter("au_id", TypeCode.String, (string)_authorField.FieldValue)); } else { _ds.SelectParameters["au_id"].DefaultValue = (string)_authorField.FieldValue; } }
else {
_ds.SelectParameters.Clear(); _ds.SelectCommand = selectStatement; } _ds.DataBind(); base.OnPreRender(e); } } }
VB.NET Code
Imports System Imports System.Drawing Imports System.ComponentModel Imports System.Web.UI.WebControls Imports System.Web.UI.WebControls.WebParts
Namespace MyWebParts
' <summary> ' WebPart to display the information of Authors
' </summary> Public Class AuthorWebPart Inherits WebPart Implements IField
Private _view As GridView
Public Sub New()
MyBase.New() End Sub
ReadOnly Property FieldValue() As Object _
Implements IField.FieldValue Get Return _view.SelectedValue End Get End Property
ReadOnly Property Schema() As PropertyDescriptor _ Implements IField.Schema
Get Return TypeDescriptor.GetProperties(Me.GetType)("FieldValue") End Get End Property
Protected Overrides Sub CreateChildControls()
_view = New GridView _view.ID = "_authorsGrid" _view.AutoGenerateColumns = True _view.DataKeyNames = New String() {"au_id"}
Dim field As CommandField = New CommandField
_view.SelectedRowStyle.BackColor = Color.Red field.ShowSelectButton = True _view.Columns.Add(field) Dim ds As SqlDataSource = New SqlDataSource
ds.ID = "_authorsDS" ds.ConnectionString = "server=carlosagmail;database=pubs;uid=sa;pwd=yourpassword"
ds.SelectCommand = "select au_id, au_lname, au_fname from authors" _view.DataSourceID = ds.ID Me.Controls.Add(ds) Me.Controls.Add(_view) End Sub
<ConnectionProvider("AuthorID")> _
Public Function GetAuthor() As IField Return Me End Function
End Class
' <summary> ' WebPart to display the information of Books
' </summary> Public Class BooksWebPart Inherits WebPart
Private _authorField As IField
Private _ds As SqlDataSource
<ConnectionConsumer("Author")> _ Public Sub SetAuthor(ByVal field As IField)
Me._authorField = field End Sub
Protected Overrides Sub CreateChildControls() Dim view As GridView = New GridView
view.ID = "_booksGrid" view.AutoGenerateColumns = True
view.DataKeyNames = New String() {"title_id"}
Dim field As CommandField = New CommandField
view.SelectedRowStyle.BackColor = Color.Red
field.ShowSelectButton = True view.Columns.Add(field)
_ds = New SqlDataSource
_ds.ID = "_booksDS"
_ds.ConnectionString = "server=carlosagmail;database=pubs;uid=sa;pwd=yourpassword" view.DataSourceID = _ds.ID
Me.Controls.Add(_ds)
Me.Controls.Add(view) End Sub
Protected Overrides Sub OnPreRender(ByVal e As EventArgs) Dim selectStatement As String = "SELECT titles.title_id, titles.title, titles.type, titles.price, titles.pubdate FROM titles" EnsureChildControls() If (Not (_authorField) Is Nothing) Then If (_ds.SelectParameters.Count = 0) Then
_ds.SelectCommand = (selectStatement + " INNER JOIN titleauthor ON titleauthor.title_id = titles.title_id WHERE (titleauthor.au_id = @au_id)") _ds.SelectParameters.Add(New Parameter("au_id", TypeCode.String, CType(_authorField.FieldValue, String))) Else _ds.SelectParameters("au_id").DefaultValue = CType(_authorField.FieldValue, String) End If
Else _ds.SelectParameters.Clear() _ds.SelectCommand = selectStatement End If _ds.DataBind()
MyBase.OnPreRender(e) End Sub End Class End Namespace
The AuthorWebPart is a very straight forward composite control that has two child
controls a SqlDataSource and a GridView. The GridView exposes a Select link button
so users can select the author. This WebPart implements System.Web.UI.WebControls.WebParts.IField
explicitly and exposes such interface using the ConnectionProvider attribute.
The BooksWebPart also defines a GridView and a SqlDataSource, however this webpart
verifies if the IField information is available and if it is, it uses that
information to filter the books. If it is not available, then it displays all the
books. This way it is completely independent from any webpart.
Running the Sample
Browse to the page:
Browse to the Sample Page
The first time you run the page you will get a not very interesting empty page, just with the WebPartPage menu in Browse mode like the following image shows:
Set the page in CatalogDisplayMode:
Now, in the drop down menu select the option "Add WebParts to this Page" and click Change
The page will show in Catalog DisplayMode so you can add new webparts to this page. In this case the only webparts that will be shown are the ones listed in the DeclarativeCatalogPart.
Add the WebParts
Now, Mark both Check Boxes and Click Add. You can see that you can add as many WebParts as you want.
Now you get a much more interesting page that allows you to minimize/restore/close parts of your page. It displays a list of all authors and a list of all books.
Creating the Connection
Now, lets link them together so you don't get all books but only the books for the selected author.
For this, select the option "Connect Web Parts on this Page" and press Change
This will set the page in Connect Mode where you can establish connections between webparts. When you are on this mode you will get a small "black arrow" just at the left of the "Minimize" verb that you can click to see the "Connect Verb"
Linking them together
Select the Connect verb in the Authors WebPart and scroll to the bottom of the page where the ConnectionZone will be visible.
Click the link "Create a connection to a Consumer" and set the Books option in the drop down so both webparts get connected. Click Connect. And then Close the Connections Zone
Finally it works!!!
Now every time you select an Author in the Authors WebPart it will display only the books for the selected author instead of the whole list.
This sample, shows how you can use several features in WebParts to create very dynamic applications.
|