On my current project I am working on using WebParts to format the pages. I needed a way to be able to add WebParts dynamically at run time based upon the default settings as well as if they are going to be shared with other sections of the web site.
I have spent about 10 hours working on how to be able to add WebParts dynamically to the CatalogPart section for the WebPartManager. I have had to search the web and look at several different posting about WebParts to finally get the desired result.
I need to give special credit to the following:
- Jesse Liberty (his article gave me the base understanding of how to implement the built in functionality of WebParts and how to use them)
- Web Parts in ASP.NET 2.0 http://ondotnet.com/pub/a/dotnet/2005/01/10/liberty.html
- Johan Danforth’s Blog (his three blog entries gave me the understanding on how to write a custom CatalogPart)
- [.NET 2.0] Adding Web Parts programmatically http://weblogs.asp.net/jdanforth/archive/2004/08/12/213542.aspx
- [.NET 2.0] Adding Web Parts programmatically (part 2) http://weblogs.asp.net/jdanforth/archive/2004/08/19/216990.aspx
- [.NET 2.0] Creating your own CatalogPart http://weblogs.asp.net/jdanforth/archive/2005/09/26/426005.aspx
The custom CatalogPart class that I came up with is as follows:
using System.Collections.Generic; using System.Web.UI.WebControls.WebParts; namespace Controls { public class WebCMSCatalogPart : CatalogPart { private Dictionary<WebPartDescription, WebPart> webParts = new Dictionary<WebPartDescription, WebPart>(); public int GetWebPartCount() { return webParts.Count; } public void AddWebPart(WebPart wp) { if (wp.ID == null || wp.ID.Length == 0) { wp.ID = string.Format("WebPart{0}", webParts.Count); } WebPartDescription wpDescription = new WebPartDescription(wp); webParts.Add(wpDescription, wp); } public override WebPartDescriptionCollection GetAvailableWebPartDescriptions() { List<WebPartDescription> list = new List<WebPartDescription>(); foreach (KeyValuePair<WebPartDescription, WebPart> kvp in this.webParts) { list.Add(kvp.Key); } return new WebPartDescriptionCollection(list); } public override WebPart GetWebPart(WebPartDescription description) { WebPart wp = null; if (webParts.ContainsKey(description) == true) { wp = webParts[description]; } return wp; } } }
To add controls to the custom CatalogPart I used the following code on the page that contains the WebParts:
Aspx Page:
<%@ Register Namespace="Controls" TagPrefix="wc" %>
<asp:CatalogZone ID="CatalogZone1" runat="server"> <ZoneTemplate> <wc:WebCMSCatalogPart ID="WebCMSCatalogPart1" runat="server" Title="Available Web Parts Catalog" /> <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1" runat="server"> <WebPartsTemplate> </WebPartsTemplate> </asp:DeclarativeCatalogPart> <asp:PageCatalogPart ID="PageCatalogPart1" runat="server" /> <asp:ImportCatalogPart ID="ImportCatalogPart1" runat="server" /> </ZoneTemplate> </asp:CatalogZone>
Code Behind Page:
protected void Page_Init(object sender, EventArgs e) { AddWebParts(); }
private void AddWebParts() { Controls.WebCMSCatalogPart cp = CatalogZone1.CatalogParts.OfType<Controls.WebCMSCatalogPart>().FirstOrDefault(); if (cp != null) { Calendar cal = new Calendar(); cal.ID = string.Format("WebPart{0}", cp.GetWebPartCount()); GenericWebPart genericWebPart = WebPartManager1.CreateWebPart(cal); genericWebPart.Title = "Calendar Control"; cp.AddWebPart(genericWebPart); Login login = new Login(); login.ID = string.Format("WebPart{0}", cp.GetWebPartCount()); genericWebPart = WebPartManager1.CreateWebPart(login); genericWebPart.Title = "Login Control"; cp.AddWebPart(genericWebPart); } }
Again I spend about 10 hours trying to get an understand of how to implement a custom CatalogPart so I could add WebParts dynamically at run time.