WebPart 102 – Adding Code

When implementing a WebPart in SharePoint 2007, make sure (firstly) that you actually NEED to do more than just some simple HTML – otherwise you’d use a Content Editor WebPart (or similar).

A WebPart is a mini web page (like an ASCX web user control in ASP.NET-land).

As we saw in this post, getting the deployment happening is a fair battle – now we’re ready to add some functionality.

There are a number of ways to get some “output” in/out of a WebPart :

Render

  • Simply do a “WriteLine” to spit out some HTML
  • There are different ways to do this too – Write, RenderBeginTag, etc
  • Basically only good for TEXT or HTML controls that don’t do much (TABLE, TD, TR, etc)

CreateChildControls

  • In order to have some sort of server side (ASP.NET) components that you can set values, respond to events, etc – you have to add them manually
  • There is a “controls collection” that you add the controls to – which are then included in the “Render” method

The following example builds on the “GrumpyWookieFeedback” WebPart from this post.  Scroll below for a download link (zip).


Render

When a new control is created, there is ONE event added : Render.

We simply updated the text being written out (as follows) :

protected override void Render(HtmlTextWriter writer)
{
    // TODO: add custom rendering code here.
    writer.Write("Grumpy Wookie was here");
}

 

This is an override method, inherited from the “System.Web.UI.WebControls.WebParts.WebPart” interface.

We’ll add a new line using the “RenderStartTag” method of the HtmlTextWriter. 

You can enter your own tag, or select from a known list of tags :

h2
 

There are a LOT of “write” methods – such as WriteAttribute, WriteEncodedUrl, WriteFullBeginTag – and so on. 

Best to experiment to see which works for your specific need.

For now, I’ll just add a “H2” tag around the text :

writer.RenderBeginTag(HtmlTextWriterTag.H2);
writer.Write("Grumpy Wookie was here");
writer.RenderEndTag(); 

 

Deploy Updated Control

  • Compile the WebPart within Visual Studio
  • Drag DLL file to GAC 9from bindebug folder
  • (Most likely) have to do IISRESET

 

And – this is the result – nothing spectacular :

h2show


CreateChildControls

OK – No more “hello world”.   We need the GrumpyWookieFeedback WebPart to have some functionality. 

In this example – I’ll add a textbox, dropdownlist (with some options) – and a button.

NOTE – you can’t just ADD the controls directly from within the “Render” method.  You have to add them to the “controls collection” for the WebPart.

To add your own ASP.NET server controls, you include an additional method (that doesn’t get added initially).

This is the “CreateChildControls” method – in which you add the code for controls such as DropDownLists, Buttons, etc – and define the properties for the controls – and any events that they will respond to.

protected override void CreateChildControls()
{

}

 

Again, this is an “override” method – you’re basically building up the WebPart to operate the same as all other SharePoint controls work – well, duhh.

 

Namespace

Ensure you have the “WebControls” namespace added to your class :

using System.Web.UI.WebControls;

 

Define Controls

You then have to define the controls within the class – not within the Render method – or the CreateChildControls method – they need to be “global” for the class.

The following code snippet shows a few controls added to the class :

TextBox txtComment;
DropDownList ddlFeedbackType;
Button btnOK;

Once again, make sure you define the controls at the “class” level.

You can now go ahead and add the code for the controls within the “CreateChildControls” method :

protected override void CreateChildControls()
{
    txtComment = new TextBox();
    this.Controls.Add(txtComment);

    ddlFeedbackType = new DropDownList();
    this.Controls.Add(ddlFeedbackType);

    btnOK = new Button();
    this.Controls.Add(btnOK);

    ChildControlsCreated = true;

}

 

The last line is important for the “interface”.  It tells SharePoint that the method has completed, and controls have been added to the collection.

 

Deploy the Control

ie. compile, GAC the DLL, IISRESET

Refresh your test page, containing the new WebPart control.

 

Where are my controls ?

If you’re wondering why the ASP.NET server controls are NOT appearing, that’s because they exist within the “controls collection” – but they haven’t been “Render”ed out to the page.

You need to include some code to spit out the controls similar to how the “H2” and text were included (above).

Controls[0].RenderControl(writer);
Controls[1].RenderControl(writer);
Controls[2].RenderControl(writer);

As the control collection is an array, you just need to write out the “0,1,2,3,…” values – but I like to include an enum for readability :

private enum WebPartControls
{
    txtComment,
    ddlFeedbackType,
    btnOK
}

 

And then, when including in the “Render” method :

Controls[(int)WebPartControls.txtComment].RenderControl(writer);
Controls[(int)WebPartControls.ddlFeedbackType].RenderControl(writer);
Controls[(int)WebPartControls.btnOK].RenderControl(writer);

 

Deploy the control – and refresh – and should look like THIS :

wihtcontrols

You can then set properties on the specific controls – such as add items to dropdown, size & text for button, etc :

ddlFeedbackType = new DropDownList();
ddlFeedbackType.Items.Add("Enquiry");
ddlFeedbackType.Items.Add("Comment");
ddlFeedbackType.Items.Add("Complaint");
ddlFeedbackType.Items.Add("Money");
this.Controls.Add(ddlFeedbackType);

 

btnOK = new Button();
btnOK.Text = "Send Feedback";
btnOK.Width = 120;
this.Controls.Add(btnOK);
 

…and include a “break” between the controls when rendered out :

Controls[(int)WebPartControls.txtComment].RenderControl(writer);
writer.Write("<BR>"); 
writer.Write("<BR>"); 
Controls[(int)WebPartControls.ddlFeedbackType].RenderControl(writer);
writer.Write("<BR>"); 
writer.Write("<BR>"); 
Controls[(int)WebPartControls.btnOK].RenderControl(writer);

wihtcontrols2

 

Event Handler

That all looks nice and fancy, but nothing happens when you click the button.  That’s because we haven’t added the code for the “event handler”.

This includes two parts – firstly, where the button is defined :

btnOK.Click += new EventHandler(btnOK_Click);

 

…and also the method (handler) code module itself :

void btnOK_Click(object sender, EventArgs e)
{

}
 
 

Do Something

We can now include some code to perform when the user clicks the button – such as send via an email, or log to an XML file – or add an item to a SharePoint list – or redirect to another page – or whatever.

For now, I’ll add a “Label” control to the Controls collection :

void btnOK_Click(object sender, EventArgs e)
{
    string strResponse = "Thanks for your " + ddlFeedbackType.SelectedValue + " : ";
    strResponse += txtComment.Text;
    strResponse += "    (received on : " + DateTime.Now.ToLongDateString() + ")";

    lblFeedback = new Label();
    lblFeedback.Text = strResponse;
    this.Controls.Add(lblFeedback);

}

 

…and then include this control (with a condition) – within the “Render” method :

if (Controls.Count == 4)
{
    writer.Write("<BR>");
    writer.Write("<BR>");
    writer.Write("<BR>");
    Controls[(int)WebPartControls.lblFeedback].RenderControl(writer);
}

 

feedback

 

That’s about it !  

You can easily add much more complex functionality – and layout – the only trick is having to actually write the specific controls using code.

 

Code Sample (Download)

I’ve bundled the example project into a zip file – click here to download.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s