How do I create custom properties in Visual Web Parts?

in this post of my Visual Web Part post series we are going to see how to setup custom properties in Visual Web Parts. As you probably know, the most interesting aspect of Visual Web Parts is the ability to configure them directly on a SharePoint page by changing properties during runtime. These properties are stored into the database and reused on each page load. This provides endless scenarios to build configurable pages.

We will follow the creation process of a simple Web Part storing addresses. This Web Part will provide custom properties that are modifiable by a SharePoint user. We will follow the steps that we already covered in detail here. The address Web Part will look like the Web Part in the next figure. We have a simple address consisting of a name, street, zip code and city. We want that these settings are configurable on each single page by our customers. image

This post is subdivided into three sections:

  • Preparing the project: we setup the Visual Web Part project and check the settings that we might want to change before deploying our Web Part
  • Personalize the Address Web Part: we see how we can add customizable properties, and how we connect them to our Visual Web Part
  • Some improvements: we make some small modifications to the Web Part that we created to improve the “look & feel” and “usability” of our Web Part
  • Points to consider: some notes to consider during Web Part development

Preparing the project

Let us jump in directly in the creation of the Visual Studio project with the Visual Web Part project template for SharePoint 2010.

  • create a new Visual Web Part project named “Examples.AddressWebPart” (if you don’t know how to do it, follow this link).
  • since the assembly name is called exactly the same, we don’t need to make further changes in the project property page
  • delete the Visual Web Part called “VisualWebPart1”
  • add a new “Visual Web Part” and call it “Address”
  • open the “Features” folder and double click on “Feature 1”. Change the feature name to “Addresses Feature” and description to “This feature activates the address-related Web Parts”. Ensure that the “Address” Web Part is listed in this feature on the right side. You see an example in the next picture:

image

  • we don’t make any changes to the package name, because it will be called like our project name. This is good for us.

Now, we are going to make small changes to our Web Part configuration files “Address.webpart” and “Elements.xml” in the “Address” container. We make these changes to complete our configuration process and to provide a better description to our Web Part on our SharePoint site.

  • Let us change the description shown in the Web Part catalog. Double click on the Address.webpart file in the Address container and change the description of the Web Part to “Displays a personalizable address on the screen”. The code will look similar to the next code snipped:
<?xml version="1.0" encoding="utf-8"?> 
  
  <?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/WebPart/v3 NS = "http://schemas.microsoft.com/WebPart/v3" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/WebPart/v3 NS = "http://schemas.microsoft.com/WebPart/v3" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/WebPart/v3 NS = "http://schemas.microsoft.com/WebPart/v3" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/WebPart/v3 NS = "http://schemas.microsoft.com/WebPart/v3" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/WebPart/v3 NS = "http://schemas.microsoft.com/WebPart/v3" />
    
       
      $Resources:core,ImportErrorMessage;
     
     
       
    Address  
    Displays a personalizable address on the screen 
      
    
  
  • Finally, we change the category associated to our Web Part in the Web Part catalog. We will change the property value to “Utilities”.
<?xml version="1.0" encoding="utf-8"?>
<?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/sharepoint/ NS = "http://schemas.microsoft.com/sharepoint/" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/sharepoint/ NS = "http://schemas.microsoft.com/sharepoint/" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/sharepoint/ NS = "http://schemas.microsoft.com/sharepoint/" /><?XML:NAMESPACE PREFIX = [default] http://schemas.microsoft.com/sharepoint/ NS = "http://schemas.microsoft.com/sharepoint/" />
    
     
        
     
    

Personalize the Address Web Part

Development of Visual Web Parts is simple if you know the most important files to change:

  • “Address.cs”: the class inheriting from the Web Part base class and used to setup personalization settings. In addition, this class is loading the web user control needed for our Visual Web Part functionalities
  • “AddressUserControl.ascx”: this controls gives us the design time capabilities of Visual Studio 2010

The basic approach is:

  • configure the properties of the Web Part class to be persisted
  • combine the Web Part class with the web user control to control the rendering behavior

First, let us add the properties that we want to persist with the Web Part framework by adding some code in the “Address.cs” file. Follow the next code example.

namespace Examples.AddressWebPart.Address  
{
     [ToolboxItemAttribute(false)]
     public class Address : WebPart
     {
         // Visual Studio might automatically update this path when you change the Visual Web Part project item.
         private const string _ascxPath = @"~/_CONTROLTEMPLATES/Examples.AddressWebPart/Address/AddressUserControl.ascx";

         [Personalizable(), WebBrowsable]
         public String Firstname { get; set; } 

         [Personalizable(), WebBrowsable]
         public String Lastname { get; set; }

         [Personalizable(), WebBrowsable]
         public String Street { get; set; }

         [Personalizable(), WebBrowsable]
         public int Zip { get; set; }

         [Personalizable(), WebBrowsable]
         public String City { get; set; }

         protected override void CreateChildControls()
         {
             Control control = Page.LoadControl(_ascxPath);
             Controls.Add(control);
         }
     }
 }

We added some basic type properties to the class. Important is to consider the attributes associated to our properties:

  • “Personalizable” tells the Web Part framework to store this property in the database
  • “WebBrowsable” tells the Web Part framework to display the property in the editor zone of your Web Part. If you don’t use this attribute, the property can be used for storage, but is not displayed in the editor zone to your end user.

You can store any type that is serializable with the Web Part framework (basic types and complex types).

if you want to make your custom class serializable, put the “Serializable” attribute on the top of your class definition. These properties are only persisted when the Web Part is in “edit mode”. So, if you change some properties in the Web Part class above, they won’t be saved in the database.

Let us see what we did until now on our SharePoint site. Deploy the solution and add the Web Part to any page. When you press the “Edit Web Part” button, you will notice the five properties that we specified before added in the “miscellaneous” category of our editor part as textboxes. In addition, each textbox has a label with text containing the property name.

image image

Start inserting some values into the textboxes and press “OK” to confirm your choice. The Web Part framework stores the values into the database and associates them with the Web Part instance that you are editing. That means, after each page load, the properties in the Web Part class are populated with the settings that you defined in the editor part. However, until now nothing happens in our Web Part because we did not add some controls for rendering into our “AddressUserControl.ascx”. Before we start adding controls, we have to make a last change to our “AddressUserControl.ascx.cs” file. You see them in the next code snipped:

namespace Examples.AddressWebPart.Address
{
     public partial class AddressUserControl : UserControl
     {
         public Address WebPart { get; set; }
     }
}

To end it, we have to make a small change in the “Address.cs” class and edit the “CreateChildControls” event:

protected override void CreateChildControls()
{
  AddressUserControl control = Page.LoadControl(_ascxPath) as AddressUserControl;
 
  if (control != null)
  {
     control.WebPart = this;
  }

  Controls.Add(control);
}

With the code changes above we are telling our “AddressUserControl” to populate the property that we specified with the instance of our Web Part. In this way, we are able to access the Web Part properties specified in the “Address.cs” class.

Finally, we are able to add some controls to our “AddressUserControl.ascx” file that looks like that (please note that I used the designer to create this code):

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>   
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AddressUserControl.ascx.cs" Inherits="Examples.AddressWebPart.Address.AddressUserControl" %>
<?xml:namespace prefix = asp /> 



-&nb

The last step is to add in the “OnPrerender” event of the “AddressUserControls.ascx.cs” file. We are simply assigning to the text properties of the labels the corresponding Web Part properties that are persisted by the Web Part framework. The code looks like that:

protected override void OnPreRender(EventArgs e)
{
  base.OnPreRender(e);
  if (this.WebPart != null)
  {
    this.lblFirstname.Text = this.WebPart.Firstname;
    this.lblLastname.Text = this.WebPart.Lastname;
    this.lblStreet.Text = this.WebPart.Street;
    this.lblZip.Text = this.WebPart.Zip.ToString();
    this.lblCity.Text = this.WebPart.City;
  }
}

Let us deploy the solution, add a Web Part to a page and modify it’s properties. The result may look like the next figure:

image

Some improvements

To end our Address development, we want to improve two aspects of our Web Part. First, we want to remove the label “Address” on the top of our Web Part when looking at our page. Something similar to the next figure: image

Second, we want to prohibit the end user, to minimize, hide or close the Web Part. In addition, we improve the editor zone by moving the properties from the “miscellaneous” section to a section that we are going to call “address settings”. Finally, we change the label associated to our city textbox to “city or town”.

image

This is done by changing some attributes and properties of our “Address.cs” class. The changes that we made are:

  1. set the “AllowMinimize” and “AllowHide” property to false to disable minimizing and hiding capabilities
  2. set the “ChromType” of the Web Part to hide the chrome around our Web Part during page load
  3. added to each property the attribute “Category("Address settings")” to move the property in the new category of our editor part
  4. added to the city property the attribute “WebDisplayName("City or Town")” to change the label associated to the textbox “city”
namespace Examples.AddressWebPart.Address  
{
    [ToolboxItemAttribute(false)]
    public class Address : WebPart
    { 
      public Address()
      {
         this.AllowMinimize = false;
         this.AllowHide = false;
         this.AllowClose = false;
         this.ChromeType = PartChromeType.None;
      }

      // Visual Studio might automatically update this path when you change the Visual Web Part project item. 15:            private const string _ascxPath = @"~/_CONTROLTEMPLATES/Examples.AddressWebPart/Address/AddressUserControl.ascx"; 

      [Personalizable(), WebBrowsable, Category("Address settings")]
      public String Firstname { get; set; }

      [Personalizable(), WebBrowsable, Category("Address settings")]
      public String Lastname { get; set; }

      [Personalizable(), WebBrowsable, Category("Address settings")]
      public String Street { get; set; }

      [Personalizable(), WebBrowsable, Category("Address settings")]
      public int Zip { get; set; }

      [Personalizable(), WebBrowsable, WebDisplayName("City or Town"), Category("Address settings")]
      public String City { get; set; }

      protected override void CreateChildControls()
      {
        AddressUserControl control = Page.LoadControl(_ascxPath) as AddressUserControl;
        if (control != null)
        { 
            control.WebPart = this;
        }
        
        Controls.Add(control);
      } 
   }
}

Points to consider

During Web Part development consider following points:

  • Never change assembly name, namespace or class name of a Web Part used by your customers. The customer will get an exception to this.
  • Never change property names that are personalized to change the description in the editor zone. Use the “WebDisplayName” instead
  • If you set a property in your Web Part class, this setting will not be stored in the database.
  • Base types are rendered automatically in your editor zone. If you want “complex” types, you need to extend the editor zone with custom code
  • Complex types must be serializable, or you will get exceptions on runtime

Summing up

In this post we created a simple address Web Part with customizable properties. We saw how to combine the Web Part class with our web user control and how to personalize some basic Web Part and Editor Part settings. If you want to get more information about Visual Web Part development, simply follow my post series.

 

Hope this helps,

Patrick

This entry was posted in Developers, Web Parts by Patrick Lamber. Bookmark the permalink.
Patrick Lamber

About Patrick Lamber

Patrick Lamber is a long-standing .NET Developer and has offered SharePoint consulting, development, and training services to customers since the launch of SharePoint 2007. He is a both a Microsoft Certified Trainer and a Microsoft Certified IT Professional, and holds Microsoft Certified Professional Development certifications for SharePoint. Patrick founded NUBO with the aim of developing a team of specialized SharePoint professionals delivering great solutions. Furthermore, in his role as SharePoint Competence Manager Patrick is also responsible for building up the SharePoint team for the company Blu Systems GmbH in Munich. Patrick speaks three languages (German, Italian, and English), meaning most of his work is focused on Italy, Germany, Austria, and Switzerland.

22 thoughts on “How do I create custom properties in Visual Web Parts?

  1. Patrick,&lt;br /&gt;&lt;br /&gt;I realize it was an interesting way to use these settings (usually we use this tool appropriately).&lt;br /&gt;&lt;br /&gt;I&amp;#39;ll save it as 4 different webparts.&lt;br /&gt;&lt;br /&gt;Thanks for the quick response,&lt;br /&gt;&lt;br /&gt;-James

  2. I think this article is pretty good, it explains the basic approach very clearly und understandable even for beginning developers. – Thx for that! &lt;br /&gt;I just have one little question:&lt;br /&gt;Why did you override CreateChildControls without calling its base Method? &lt;br /&gt;(like this):&lt;br /&gt; base.CreateChildControls();

  3. Thanks for the write up. I'm confused about the .ASHX file, though… I don't have an ASHX file. I thought maybe it was a typo and you meant the ASCX file, but I made the changes there and it didn't seem to work…

    Thanks

  4. Thanks Patrick, I had issues with multiple web parts on the same page, they kinda shared each others' properties. I followed the steps mentioned in your blog and now its working like a charm :) thank again

  5. Hi Michael,
    indeed, this was a type. I will correct it in the blog.

    Do you have still other issues?

    br,
    patrick

  6. Hi

    Good post and easy to implement. I have built a visual web part that takes the task list name property. I notice however, even though the task list name is valid ( I check for this) and is persisted between requests . The web part does not always display my GridView when I click ok and return from the edit web part panel. I sometimes have to refresh the page if this is the first time the property has been entered.

    I have removed the !IsPostBack() as this was sometimes preventing the me DataSource from being populated and bound.

    I wondered if you had seen this behaviour?

  7. Hello,
    this happens because your gridview is databinding before the WebPart property is populated.

    To solve this issue I typically postpone the databinding of the gridview programmatically in the OnPreRender method of the control. In that way I am sure that it is done in the last moment.

    Anything after the OnInit is also good enough since in the WebPart properties are filled-out in the oninit method of the control.

    Hope this helps,
    patrick

  8. Brilliant post, I just wanted to know If I am able to adapt this solution to my client requirements. they have an Office 365 environment with an MSO SharePoint 2010 intranet. they want me to build a slideshow webpart with custom properties like image size, transition etc. Do I need to create a sandboxed solution for an MSO environment? How will I transfer my finished webpart to the client for testing once it is finished? thanks in advance

  9. I saw someone had issues with multiple web parts on the same page, they kinda shared each others' properties.

    I have a similar issue and can't figure out to fix it

  10. Hello,
    please have a look at this blog post. Maybe it is the solution for you.

    multiple-instances-of-webpart-with-custom-editorpart-and-silverlight-wont-work

    br,
    patrick

  11. Patrick

    Thanks for the advice. moving the datasource population code to the onPreLoad even worked well and allows the data to be displayed instantly after my property is set. I wonder if there are any gotchas I need to be aware having the DataSou
    ce code here as opposed on PageLoad.

  12. Im getting this error?

    System.Web.UI.Control' does not contain a definition for 'WebPart' and no extension method 'WebPart' accepting a first argument of type 'System.Web.UI.Control' could be found (are you missing a using directive or an assembly reference?)

    Any suggestions?

  13. While web part properties that do not have any 'logic' work fine.

    [Personalizable(), WebBrowsable]
    public String DebugUser { get; set; }

    Something that happened to me is that web part properties that perform operations to get the value, cause the web part to fail to load in the 'add web part' pane, etc. Such as,

    private bool _IsDebug;
    [Personalizable(), WebBrowsable]
    public bool IsDebug
    {
    get
    {
    // NOTE — The following line causes the web part to not load…
    // The var qsIsDebug is a simple query string value member.
    if (qsIsDebug) return true;
    return _IsDebug;
    }
    set { _IsDebug = value; }
    }

    protected bool qsIsDebug
    {
    get
    {
    string s = Page.Request["debug"];
    bool debug;
    if (string.IsNullOrEmpty(s) || !bool.TryParse(s, out debug))
    debug = false;
    return debug;
    }
    }

    Thanks,
    Scott.

  14. This is just the information I am finding everywhere. Thanks for your blog, I just subscribe your blog. This is a nice blog.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Powered by Sweet Captcha
Verify your real existence,
Drag the "sale!" on the sticker.
  • captcha
  • captcha
  • captcha
  • captcha