Applies To:Studio Enterprise
Author:John Juback
Published On:7/12/2006

Windows SharePoint Services allows organizations to create Web portals for information sharing and document collaboration. It supports modular page design and personalization through the use of Web Parts, which administrators and end users alike can combine to form rich, customizable page views. Developers can leverage their knowledge of ASP.NET and the functionality of ComponentOne Studio Enterprise to create innovative Web Parts that extend the capabilities of SharePoint.


This article describes how to use the ASP.NET controls in Studio Enterprise to create a simple Web Part that displays a chart, then examines a more complex sample project that uses a data-bound chart, grid, and report viewer.


Microsoft Visual Studio


The sample projects described in this article are intended to be built with Microsoft Visual Studio .NET 2003, not Visual Studio 2005. This is because Windows SharePoint Services runs under the .NET Framework 1.1 by default. It follows that the .NET 1.x versions of the ComponentOne ASP.NET controls are also required.


Although Windows SharePoint Services with Service Pack 2 does support the .NET Framework 2.0, the 2.0 versions of the ComponentOne ASP.NET controls have not been tested in that environment. It is also important to note that ASP.NET 2.0 Web Parts and SharePoint Web Parts are different. You cannot use ASP.NET 2.0 Web Parts as Web Parts per se in SharePoint without a wrapper control. For more information on Windows SharePoint Services SP2, CLR versions, and Web Part development, see the following article:


    Microsoft Office Assistance: Service Pack 2 for Windows SharePoint Services and SharePoint Portal Server 2003


ComponentOne Studio Enterprise


The sample projects also require ComponentOne Studio Enterprise 2006 v2 or later. You do not need to have Studio Enterprise (or Visual Studio, for that matter) installed on the SharePoint server. You can build Web Parts on your development machine, then deploy them to the server for testing. However, the following DLL versions are required in order for the C1 components to run in partial trust scenarios:


C1.Win.C1Chart.dll1.0.20062.16182
C1.Web.C1WebChart.dll1.0.20062.16182
C1.Web.C1WebGrid.dll1.1.20062.64
C1.Win.C1Report.dll2.5.20062.216
C1.Web.C1WebReport.dll2.5.20062.216

As stated earlier, these are the .NET 1.x controls.


Web Part Library Templates


You will also need to download and install the Web Part Library templates on your development machine.


    Download Web Part Templates for Visual Studio .NET


Note that the installation will prompt you for the path to the Microsoft.SharePoint.dll. By default, this path is:


C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\ISAPI

If you are installing the templates on a development machine that is not a SharePoint server, you will need to supply the correct path on the server. Alternatively, you can copy this file to your development machine, then supply that location when prompted by the installation program. This way, you can continue to build your Web Part assembly even when the server is unavailable.


This is a good time to secure as many administrative privileges as you can wrangle on the SharePoint server, as you will eventually need to be able to copy files to the server, edit configuration files, restart IIS, and run SharePoint Central Administration.


Creating a Web Part Project


In Visual Studio, open a new C# project named C1WebPartSample based on the Web Part Library template installed earlier. A Visual Basic template is also available; however, all of the code samples in this article use C#.



This creates a class library project with the following files:


AssemblyInfo.csAssembly version information. You will need to modify this file to associate a Strong Name Key with the assembly.
WebPart1.csA boilerplate Web Part class that inherits from Microsoft.SharePoint.WebPartPages.WebPart.
WebPart1.dwpAn XML description file used to import the Web Part into SharePoint.
Manifest.xmlAn XML manifest used when creating CAB files for Web Part deployment (not covered in this article).

Adding C1 References


On the Project menu, click Add Reference, then select the following component names in the .NET tab:



  • C1.Common

  • ComponentOne C1Chart

  • ComponentOne C1WebChart


If you do not see these components listed, you can browse for the following files:



  • C1.Common.dll

  • C1.Win.C1Chart.dll

  • C1.Web.C1WebChart.dll


In Solution Explorer, expand the References node and ensure that CopyLocal is set to True for all C1 references.


Modifying the Web Part Class


The Web Part class generated by the template contains sample code that shows how to implement a string property and a custom tool part. We don't really need this code for our chart sample, so open WebPart1.cs and replace the entire file with the following code:


using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using C1.Web.C1WebChart;
 
namespace C1WebPartSample
{
public class WebPart1 : Microsoft.SharePoint.WebPartPages.WebPart
{
private C1WebChart chart = null;
 
protected override void RenderWebPart(HtmlTextWriter output)
{
EnsureChildControls();
chart.RenderControl(output);
}
 
protected override void CreateChildControls()
{
// create a new chart
base.CreateChildControls();
chart = new C1WebChart();
 
// use HttpHandler method, do not use session state
chart.ImageRenderMethod = ImageRenderMethodEnum.HttpHandler;
chart.ImageTransferMethod = ImageTransferMethodEnum.Cache;
chart.ImageIdGeneration = ImageIdGenerationEnum.Unique;
chart.ImageUri = "";
 
// add the chart to this Web Part
this.Controls.Add(chart);
}
}
}

At a minimum, a class that derives from WebPart must implement two overrides in order to host a Web control:


RenderWebPartCalls EnsureChildControls, then calls the RenderControl method of the child.
CreateChildControlsCreates the child control, optionally customizes it, then adds it to the Controls collection of the Web Part.

The four statements that follow the creation of the chart are specific to the C1WebChart component. They are included to configure the built-in HttpHandler to transfer chart images directly to the client without generating temporary files.


Modifying the Web Part Description


Edit the file WebPart1.dwp and modify the tag:




WebPart1
Sample WebPart using the C1WebChart control.
C1WebPartSample
C1WebPartSample.WebPart1


This string appears as a ToolTip when the user hovers the mouse over the name of the Web Part in SharePoint.


Creating a Strong Name Key


In order for SharePoint to use a custom Web Part assembly, it must be strongly named. Open a Visual Studio .NET 2003 Command Prompt, then change the current directory to the project root folder and type:


sn -k C1WebPartSample.snk

Edit the file AssemblyInfo.cs and change the AssemblyKeyFile attribute near the end of the file to:


[assembly: AssemblyKeyFile("..\\..\\C1WebPartSample.snk")]

Licensing C1 Components


Create a text file named licenses.licx in the project root directory and add the following line:


C1.Web.C1WebChart.C1WebChart, C1.Web.C1WebChart

Add this file to the project as an embedded resource. This will cause the appropriate license key to be embedded in the DLL whenever you build the project.


At this point, you should be able to successfully build the Web Part assembly C1WebPartSample.dll.


Copying Assemblies to the SharePoint Server


First, locate the virtual root of the SharePoint portal where you want to deploy the Web Part. For the default web site, this is typically:


C:\Inetpub\wwwroot

If there is already a bin folder under this virtual root, use it as the destination folder; otherwise, create an empty folder named bin. Copy the custom Web Part assembly along with the C1 assemblies to this bin folder on the SharePoint server:



  • C1WebPartSample.dll

  • C1.Common.dll

  • C1.Win.C1Chart.dll

  • C1.Web.C1WebChart.dll


Copying Assemblies to the Global Assembly Cache


On the SharePoint server, using Windows Explorer, drag the same four DLLs to the Global Assembly Cache (GAC). For a typical Windows installation, the GAC resides in the following folder:


C:\WINDOWS\assembly

Special Case: HttpHandler Implementations


The following step is only needed for controls such as C1WebChart that provide an HttpHandler implementation. On the SharePoint server, copy the C1 chart and common DLLs to:


C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\LAYOUTS\BIN

You do not need to copy C1WebPartSample.dll, just the C1 assemblies. If you do not perform this step, your Web Part will still function, but some links in your SharePoint pages (such as Site Settings) will break. If you see a plain text error message that reads "File not found," this is probably why.


Marking the Web Part Assembly as Safe


Edit the web.config file for the virtual root of the SharePoint portal (at the same level as the bin folder where you previously copied the assemblies). It is a good idea to make a backup copy of this file first. Mark the custom assembly as safe by appending an entry to the section:





(default SharePoint assemblies...)
<SafeControl Assembly="C1WebPartSample, Version=1.0.0.0, Culture=neutral"
Namespace="C1WebPartSample" TypeName="*" Safe="True" />

Only the tag needs to be added. The other lines are listed here to provide context. Keep the file open for the next step.


Registering the HttpHandler


The chart's HttpHandler also needs to be registered by prepending the following tag to the section:






(default SharePoint handlers...)

Note that the chart's handler must precede the default SharePoint handlers, since it has a specific path (c1chartimage.aspx) that must take precedence over the general path (*.aspx) associated with the default handlers.


Restarting IIS


In order for these configuration changes to take effect, you should run iisreset on the SharePoint server, either from a command prompt or the Run command on the Start menu.


Now that you have successfully built and deployed the assembly, you are ready to see it in action. Navigate to the desired page in SharePoint. It is a good idea to set up a test page for Web Part deployment to avoid disrupting other pages (not to mention your co-workers).


If the link in the upper right corner of the page reads Modify Shared Page, you should switch to Personal View so that other users do not see the changes you make while you are testing your Web Parts. Although this is not required, doing so allows multiple developers to use the same test page simultaneously. To leave Shared View, click Modify Shared Page and select Personal View from the dropdown menu.



The link now reads Modify My Page. Click the link, point to Add Web Parts, and choose Import from the submenu.



A panel labeled Add Web Parts now appears on the right side of the page. Click the Browse button and locate the file WebPart1.dwp in the project root directory on your development machine. After you have selected the file, click the Upload button. The panel should now look like this:



Hover the mouse over the highlighted text WebPart1 and notice that the ToolTip displays the contents of the tag from WebPart1.dwp. Now drag WebPart1 (either the icon or the text) to the desired location on the page.



As shown in the preceding figure, the Web Part renders a default line chart at a fixed size. Note that if you switch to Shared View, the Web Part is no longer present, but if you switch back to Personal View (even after closing your browser), the Web Part reappears.


To restore the personal view of the page to its default state, click the Modify My Page link, select Reset Page Content from the dropdown menu, then click OK to dismiss the confirmation message box.


The remainder of this article describes a sample project (written in C#) that demonstrates the use of the C1WebReport and C1WebGrid controls in addition to C1WebChart. You can download the project by visiting the following link:


    C1WebPartSample.zip


Unzip the archive into an empty folder, preserving directory structure.


Configuring Excluded Paths in SharePoint


The sample project expects to find XML files and an Access database in the webparts_data virtual root on the SharePoint server. It also expects to find C1WebGrid scripts and images in the c1webgrid_client virtual root. Therefore, you should copy both folders from the location where you unzipped the archive to the virtual root of the SharePoint portal. For the default web site, this is typically:


C:\Inetpub\wwwroot

You must also configure both folders as excluded directories to prevent SharePoint from handling URL requests in the webparts_data and c1webgrid_client virtual roots. To do this, you will need to perform the following steps on the SharePoint server:



  1. Click Start, point to Administrative Tools, then click SharePoint Central Administration.

  2. In the Virtual Server Configuration group, click Configure virtual server settings.

  3. Click the link corresponding to the virtual server you want to configure (such as Default Web Site).

  4. In the Virtual Server Management group, click Define managed paths.

  5. In the Add a New Path section, enter webparts_data in the Path box.

  6. Select the Excluded path option.



After you complete the operation by clicking the OK button at the bottom of the page, the specified virtual root will appear in the list of excluded paths:



Repeat steps 5 and 6 for c1webgrid_client, then click OK.


The previous example (WebPart1) hosted a default chart without attempting to change either the appearance of the chart or its underlying data. Let's examine a more practical example that uses data binding to plot the contents of an XML data file.


The easiest way to configure the C1WebChart component is to use its Chart Wizard and Chart Properties dialogs at design time. Unfortunately, the Web Part Library templates do not provide a design surface for child controls. You can work around this by creating a separate ASP.NET project with one or more Web Forms containing an instance of the C1WebChart component. Use the ASP.NET project to design and test the charts, then use the Save Chart verb at design time to export the chart properties as an XML file (with a .chart2dxml extension). In the code for your Web Part class, call the chart's LoadChartFromFile method to apply the saved property values.


The sample project contains a data file, CategorySalesByQuarter.xml, in the webparts_data subfolder. The general structure of this file is as follows:



Beverages
106903
87313.8
25260.94
48390.42


Condiments
29734.44
34388.79
15769.92
26153.9

The webparts_data subfolder also contains a file named C1WebChartSample.chart2dxml, which configures a chart with the following characteristics:


Chart Type2D Bar Chart
Data SeriesQ1, Q2, Q3, Q4
Data BindingX.DataField = CategoryName (for all data series), Y.DataField = Q1 through Q4 (one per data series)
LegendVisible = True, Position = South

The complete source code for the Web Part class C1WebChartSample.cs is as follows:


using System;
using System.ComponentModel;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using C1.Web.C1WebChart;
 
namespace C1WebPartSample
{
public class C1WebChartSample : Microsoft.SharePoint.WebPartPages.WebPart
{
private C1WebChart chart = null;
 
protected override void RenderWebPart(HtmlTextWriter output)
{
EnsureChildControls();
CustomizeChart(chart);
chart.RenderControl(output);
}
 
protected override void CreateChildControls()
{
// create a new chart
base.CreateChildControls();
chart = new C1WebChart();
 
// use HttpHandler method, do not use session state
chart.ImageRenderMethod = ImageRenderMethodEnum.HttpHandler;
chart.ImageTransferMethod = ImageTransferMethodEnum.Cache;
chart.ImageIdGeneration = ImageIdGenerationEnum.Unique;
chart.ImageUri = "";
 
// add the chart to this Web Part
this.Controls.Add(chart);
}
 
private void CustomizeChart(C1WebChart chart)
{
try
{
DataSet ds = new DataSet();
ds.ReadXml(Page.MapPath("/webparts_data/CategorySalesByQuarter.xml"));
chart.LoadChartFromFile(Page.MapPath("/webparts_data/C1WebChartSample.chart2dxml"));
chart.Width = Unit.Pixel(576);
chart.Height = Unit.Pixel(424);
chart.DataSource = ds.Tables[0];
chart.DataBind();
}
catch (Exception e)
{
chart.Header.Text = e.Message;
chart.Header.Visible = true;
}
}
}
}

Note that this code is almost the same as the previous example (WebPart1) with the exception of the private member CustomizeChart, which is called by the RenderWebPart override just before the chart control is rendered. CustomizeChart does the following:



  • Initializes a DataSet from an XML file.

  • Loads previously saved chart properties from an XML file.

  • Sets the dimensions of the chart (576 pixels wide by 424 pixels high).

  • Binds the chart to the first table in the DataSet.

  • Displays error messages (if any) in the chart header.


This code expects to find both XML data files in the webparts_data virtual root on the SharePoint server, which you should have configured as an excluded directory. If you have already done so, you can build and deploy the project. You will not need to repeat the steps for deploying the C1 common and chart DLLs, but you will need to redeploy your custom Web Parts assembly as follows:



  1. Copy C1WebPartSample.dll to C:\Inetpub\wwwroot\bin on the SharePoint server.

  2. Using Windows Explorer on the SharePoint server, drag C1WebPartSample.dll to the GAC.

  3. At the command prompt, run iisreset.


To use the new Web Part, navigate to your test page in SharePoint, import C1WebChartSample.dwp as shown earlier, and drag the item named C1WebChart Sample Web Part to the desired location on the page. You should see a two-dimensional bar chart that looks like this:



As with the C1WebChart sample, the C1WebReport sample uses the webparts_data virtual root to locate its data files. The report definition file, C1WebReportSample.xml, was created using the C1Report Designer. This file in turn references an Access database, C1StudioLiveExamples.mdb, in the same physical location on the SharePoint server (assumed to be C:\Inetpub\wwwroot\webparts_data).


The complete source code for the Web Part class C1WebReportSample.cs is as follows:


using System;
using System.ComponentModel;
using System.Data;
using System.Xml;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using C1.Web.C1WebReport;
 
namespace C1WebPartSample
{
public class C1WebReportSample : Microsoft.SharePoint.WebPartPages.WebPart
{
private C1WebReport report = null;
 
protected override void RenderWebPart(HtmlTextWriter output)
{
EnsureChildControls();
report.RenderControl(output);
}
 
protected override void CreateChildControls()
{
// create a new report viewer
base.CreateChildControls();
report = new C1WebReport();
CustomizeReport(report);
 
// add the report viewer to this Web Part
this.Controls.Add(report);
}
 
private void CustomizeReport(C1WebReport report)
{
try
{
report.ImageRenderMethod = ImageRenderMethodEnum.HttpHandler;
report.ReportSource.FileName = Page.MapPath("/webparts_data/C1WebReportSample.xml");
report.ReportSource.ReportName = "Products by Category";
}
catch (Exception e)
{
report.NavigationBar.Text = e.Message;
report.NavigationBar.Visible = true;
}
}
}
}

Note that the C1WebReport component also uses an HttpHandler to return page requests. Therefore, you need to perform the same administrative tasks as outlined in the initial C1WebChart sample.


Copy the following assemblies to C:\Inetpub\wwwroot\bin on the SharePoint server:



  • C1.Win.C1Report.dll

  • C1.Web.C1WebReport.dll


On the SharePoint server, using Windows Explorer, drag the same two DLLs to the GAC. Also, copy them to:


C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\LAYOUTS\BIN

On the SharePoint server, the custom assembly should already be marked as safe in the web.config file. However, the C1WebReport HttpHandler must be added to the section before the default SharePoint handlers:







(default SharePoint handlers...)

Finally, run iisreset on the SharePoint server. When added to a page, the C1WebReport Sample Web Part looks like this:



The C1WebGrid sample demonstrates how to add custom properties to a Web Part. The GroupBy property specifies the grid column to use for grouping rows, if any. The Expanded property controls whether grouped rows are automatically expanded (if True) or collapsed (if False).


The CustomizeGrid method does most of the actual work. It is called in the CreateChildControls override and also whenever a custom property value is changed. If the grid is newly created, no columns exist, therefore the grid's LoadLayout method is called to create them from an XML layout file. If the value of the GroupBy property is not None, the method adds the appropriate column to the GroupedColumns collection and also converts the boolean Expanded property to the correct OutlineModeEnum value for that column.


Note the GetToolParts override, which causes the custom properties to appear at the top of the editing panel.


The complete source code for the Web Part class C1WebGridSample.cs is as follows:


using System;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using C1.Web.C1WebGrid;
 
namespace C1WebPartSample
{
[ToolboxData(""),
XmlRoot(Namespace="C1WebPartSample")]
public class C1WebGridSample : Microsoft.SharePoint.WebPartPages.WebPart
{
public enum GroupByColumns
{
None = 0,
Category = 2,
Supplier = 3,
Country = 4,
City = 5
};
 
private C1WebGrid grid = null;
private const GroupByColumns defaultGrouping = GroupByColumns.None;
private GroupByColumns grouping = defaultGrouping;
p rivate const bool defaultExpanded = false;
private bool expanded = defaultExpanded;
 
protected override void RenderWebPart(HtmlTextWriter output)
{
EnsureChildControls();
grid.RenderControl(output);
}
 
protected override void CreateChildControls()
{
// create a new grid
base.CreateChildControls();
grid = new C1WebGrid();
 
// add the grid to this Web Part
this.Controls.Add(grid);
CustomizeGrid(grid);
}
 
public virtual void CustomizeGrid(C1WebGrid grid)
{
if (grid.Columns.Count == 0)
grid.LoadLayout(Page.MapPath("/webparts_data/C1WebGridSample.xml"));
 
DataView dv = GetDataSource() as DataView;
grid.GroupedColumns.Clear();
 
if (grouping != GroupByColumns.None)
{
int n = System.Convert.ToInt16(grouping);
grid.GroupedColumns.Add(grid.Columns[n]);
C1BoundColumn bc = grid.Columns[n] as C1BoundColumn;
bc.GroupInfo.OutlineMode = expanded ?
OutlineModeEnum.StartExpanded : OutlineModeEnum.StartCollapsed;
dv.Sort = bc.DataField;
}
 
grid.DataSource = dv;
grid.DataBind();
}
 
private object GetDataSource()
{
string connect = @"Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=C:\\Inetpub\\wwwroot\\webparts_data\\C1StudioLiveExamples.mdb;
Persist Security Info=False";
string command = @"SELECT Products.ProductID AS ID,
Products.ProductName AS Product, Categories.CategoryName AS Category,
Suppliers.CompanyName AS Supplier, Suppliers.Country, Suppliers.City
FROM ((Products INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID)
INNER JOIN Suppliers ON Products.SupplierID = Suppliers.SupplierID)";
OleDbDataAdapter da = new OleDbDataAdapter(command, connect);
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = ds.Tables[0];
return dt.DefaultView;
}
 
public override ToolPart[] GetToolParts()
{
ToolPart[] toolparts = new ToolPart[]
{
new CustomPropertyToolPart(),
new WebPartToolPart()
};
 
return toolparts;
}
 
[Browsable(true),
DefaultValue(defaultGrouping),
WebPartStorage(Storage.Personal),
Category("Settings"),
FriendlyName("Group by Column"),
Description("Select the grouping column, or None."),
XmlElement(ElementName="GroupBy")]
public GroupByColumns GroupBy
{
get { return grouping; }
set { grouping = value; if (grid != null) CustomizeGrid(grid); }
}
 
[Browsable(true),
DefaultValue(defaultExpanded),
WebPartStorage(Storage.Personal),
Category("Settings"),
FriendlyName("Expand grouped rows"),
Description("Check to expand all grouped rows, clear to collapse them."),
XmlElement(ElementName="Expanded")]
public bool Expanded
{
get { return expanded; }
set { expanded = value; if (grid != null) CustomizeGrid(grid); }
}
}
}

When added to a page, the C1WebGrid Sample Web Part looks like this:



In the title bar for the Web Part, click the arrow on the right and choose Modify My Web Part from the dropdown menu. Expand the Settings node in the panel on the right, select Country from the Group by Column dropdown, check the box labeled Expand grouped rows, then click the Apply or OK button. The grid will reconfigure itself to display expandable row groups for each distinct country value, as shown in the following figure:



To make it more convenient to design child controls, copy an existing WebForm from an ASP.NET project to use as a design surface for setting control properties and creating XML files for C1WebChart, C1WebGrid, and C1WebReport.


To automate the deployment process, add a custom build step to copy the required DLLs to the bin directory on the SharePoint server. The sample project actually does a bit more:


copy $(TargetDir)*.dll \\yourserver\c$\inetpub\wwwroot\bin
copy $(ProjectDir)assembly.lst \\yourserver\c$\inetpub\wwwroot\bin

The file assembly.lst contains a list of the required assemblies:


C1.Common.dll
C1.Web.C1WebChart.dll
C1.Web.C1WebGrid.dll
C1.Web.C1WebReport.dll
C1.Win.C1Chart.dll
C1.Win.C1Report.dll
C1WebPartSample.dll

The bin directory on the server contains a batch file that looks something like this:


cd c:\inetpub\wwwroot\bin
if not exist assembly.lst goto done
set framework=c:\windows\microsoft.net\framework\v1.1.4322
%framework%\gacutil /il assembly.lst /f
del assembly.lst
iisreset
goto done
:done

In other words, when a build succeeds, the DLLs are copied to the bin directory along with a manifest file. When the batch file is run on the server, it does nothing if no manifest file is found. If a manifest file is found, it runs the gacutil command to copy the itemized files to the GAC, deletes the manifest file, then runs iisreset.


For more information on developing Web Parts for use in SharePoint, see the following articles:


    A Developer's Introduction to Web Parts


 


    Using Visual Studio .NET to Create Web Parts


 


    Macaw TraceInfo WebPart