Wednesday, September 06, 2006

Usercontrols (ascx), webparts and SharePoint 2007

One of the few things we are still missing in Visual Studio 2005 is the ability to visually design webparts for SharePoint 2007. In ASP.Net 2.0 you can use a web user control (ascx) as web part when it implements the IWebPart interface because  of the ASP.Net 2.0 GenericWebPart class . The GenericWebPart control exists to provide a run-time wrapper for server controls that are not WebPart controls, so that such controls can be used in Web Parts pages and applications. Unfortunately, this GenericWebPart is not available SharePoint 2007 - so you have to build your own wrapper - but this is not very hard as I will show in this posting.




First create an empty web site, afterwards add one user control wpgrid.ascx  To make things easier, uncheck the "Place code in a separate file" when adding the user control.  Switch to design view and add a GridView Control - let's call it gvDemo, set autogeneratecolumns to false and add one bound column (Datafield=Title). Now create a directory usercontrols at the root of your SharePoint site - for my default SharePoint 2007 site, this is C:\Inetpub\wwwroot\wss\VirtualDirectories\80. Copy the wpgrid.ascx file to this location.

Now let's create a new web part - as you probably already know, you can now uses ASP.Net 2.0 webparts in SharePoint 2007 - if you don't have any experience with web parts - check out Marts  - Create a SharePoint 2007 web part step by step. The web part will show the title of all items in a list in the grid with paging enabled  - so first create a web part property with the name of list you want to show.

 

public class UCWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
private UserControl usercontrol;
private GridView gvDemo;
private const string defaultlist = "";
private string _listtolink = defaultlist;
protected DataTable dtDemo = null;

[Personalizable(), WebBrowsable(),
WebDisplayName("List to display"),
WebDescription("Name of the list in this site to display")]
public string ListToLink
{
get { return _listtolink; }
set { _listtolink = value; }
}

 


 


Override the CreateChildControls method, where you will load the user control, set the necessary properties and create an event handler to implement the paging on the gridview.


 

protected override void CreateChildControls()
{
try
{
base.CreateChildControls();
this.Controls.Clear();
this.GetData();
usercontrol = (UserControl)Page.LoadControl(@"/usercontrols/wpgrid.ascx");

gvDemo = (GridView)this.usercontrol.FindControl("gvDemo");
gvDemo.AllowPaging = true;
gvDemo.DataSource = dtDemo;
gvDemo.PageSize = 3;
gvDemo.PageIndexChanging += new GridViewPageEventHandler(gvDemo_PageIndexChanging);
this.Controls.Add(usercontrol);

gvDemo.DataBind();


}
catch (Exception ex)
{
EventLog.WriteEntry("WebParts", "UCWebPart" + ex.ToString());
}
}

void gvDemo_PageIndexChanging(object sender, GridViewPageEventArgs e)
{

gvDemo.PageIndex = e.NewPageIndex;
gvDemo.DataBind();
}

 


The GetData() method loads the DataTable with the title of the different items in the list:


 

private void GetData()
{

try
{
if (ListToLink.Length > 0)
{
dtDemo = new DataTable();
dtDemo.Columns.Add("Title", Type.GetType("System.String"));

SPWeb site = SPContext.Current.Web;
SPList list = site.Lists[_listtolink];

foreach (SPListItem item in list.Items)
{
DataRow newRow = dtDemo.NewRow();
newRow["Title"] = item["Title"];
dtDemo.Rows.Add(newRow);

}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("WebParts", "UCWebPart - Retrieving items from " + _listtolink + "-" + ex.ToString(), EventLogEntryType.Error);
}
}

 




PS. You can also use the  SmartPart v2 (aka SonOfSmartPart) to load ASP.Net 2.0 user controls in SharePoint 2007 web parts ... but as you have seen above, it is quite easy to do it yourself...


Tags: , , , , , ,


Currently listening : Adema - Unstable Disc 1

21 comments:

  1. Anonymous6:14 PM

    Pretty cool way of getting the designer to work. Good post.

    -Mark

    ReplyDelete
  2. Anonymous9:38 AM

    I have done all the steps until saving the user control to the root.Do u mean that i have to do inline code ?please give me steps in detail.

    ReplyDelete
  3. I think it is better to save the usercontrol in a separate directory. You can indeed use inline code within your usercontrol - if you want to use the code behind model you will need to deploy your usercontrol project dlls as well.

    ReplyDelete
  4. Anonymous8:46 AM

    Great article. It inspired me to create my own UserControl WebPart based on ASP.NET 2.0. I hope I can create it as dynamically as SmartPart is today.

    ReplyDelete
  5. Anonymous8:48 AM

    Great article. It inspired me to create my own UserControl WebPart based on ASP.NET 2.0. I hope I can create it as dynamically as SmartPart is today

    ReplyDelete
  6. Anonymous6:57 PM

    Everytime I try to call Page.LoadControl(@"/usercontrols/myontrol.ascx"); it trows an error stating it cant find the file. however I can browse to a page that has the control on it. ie http://mysite/usercontols/mycontrol.aspx. it loads the control fine. what am I doing wrong

    ReplyDelete
  7. Anonymous5:24 PM

    Where can I find the code for download?

    Thanks

    Gibt es das Beispiel auch zum Download?

    Danke

    ReplyDelete
  8. Wow this is hard work. Can you point me in the right direction please?
    I am trying to write a web part for MOSS 2007, which will show the results of a stored procedure (SQL 2005). The results are images.

    The stored procedure has a single parameter - EMPID, which is the employee ID, the employee table links to an images table (There are many related images for each employee) so i just want to be able to enter the EMPID (either by passing it from another webpart or entering it into the web part properties when i add the webpart to the page) and the webpart show all related images.

    Thank you for your time.

    Simon

    ReplyDelete
  9. Anonymous9:49 AM

    Nice post.

    However I run into some security issues when I load the usercontrol.

    Security Exception
    Description: The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.

    Exception Details: System.Security.SecurityException: Request failed.


    Can you please help?

    ReplyDelete
  10. Make sure that you modify the web.config of SharePoint so that it can access the file system. By default SharePoint webparts are configured to run as semi-trusted. Either change the trust level to Full or associate a custom Code Acces Policy to your web part...

    ReplyDelete
  11. Finally found the article that helped me get over the hump. Web Part loading User Control works great!

    ReplyDelete
  12. Will partial class work with the .ascx control?

    ReplyDelete
  13. No, this will not work with partial classes

    ReplyDelete
  14. I am developing a webpart with a toolpart having custom properties. I need to associate my custom property which is a file path from user's local machine with an .ascx file where the user will be able to pick a file path.
    I have used following approach:

    [Category("Custom Properties")]
    [WebPartStorage(Storage.Personal)]
    [FriendlyNameAttribute("Image URL")]
    [Description("Type Image URL here.")]
    [Browsable(true)]
    [XmlElement(ElementName = "ImageURL")]
    [DefaultValue(""), HtmlDesigner(BrowserBuilderType.Dynamic)]


    public string ImageURL
    {
    get
    {
    return m_ImageUrl;
    }
    set
    {
    m_ImageUrl = value;
    }
    }



    Also I have overridden following method:

    protected override string GetCustomBuilder(string propertyName)
    {
    if (propertyName == "ImageURL")
    {
    ReplaceTokens("~/_controltemplates/BrowseImage.ascx");
    }
    else
    {
    return null;
    }
    }

    I get an unexpected error when i try to load this builder page from the custom property control on the toolpart.
    Kindly help.

    ReplyDelete
  15. Were you able to use custom Code Access Policy in the WSP file using this method?

    ReplyDelete
  16. Anonymous11:23 PM

    wow, great article. thanks a lot.

    ReplyDelete
  17. Nice article.
    When I try this, the webpart doesn't load in SharePoint. When I debug it, the Page object for Page.LoadControl is null, what am I doing wrong?

    ReplyDelete
  18. Make sure that you have your ascx in the correct location

    ReplyDelete
  19. Can some one help me, I am getting an unexcepted error when I add the webpart wrapped with a usercontrl, I tried to set the trustlevel to Full in Web.config file, but after that I am getting an unknown error. Please help.

    Regards
    Jam

    ReplyDelete
  20. reply to Boss,

    you can place the user control in

    web server extension\12\template\controltemplates folder, after that you can access this control in any site if you want.

    the path that need to enter in the page.loadcontrol method is

    ~\controltemplates/yourcontrol.ascx

    if some thing i forgot to write, or it didnt work let me know.

    ReplyDelete
  21. Thanks, For the gr8 article. My usercontrol loads properly and is working,but i have a porblem.The button inside my user control is not firing the Click event.do i need to do something different to catch that.

    Chandan

    ReplyDelete