Share via


Exercise 5: Creating a Visual Web Part with AJAX Behavior

Now you will add a second Web Part using the Visual Web Part template. This makes it possible to create the UI for a Web Part using an ASP.NET User Control and the Visual Studio User Control Designer. You will also use the UpdatePanel control from ASP.NET AJAX to give your Web Part a Web 2.0 user experience eliminating postbacks.

  1. Add a new Web Part to the ContosoWebParts project named ListInspector.
    1. Right-click on the ContosoWebParts project in Solution Explorer and select Add » New Item.
    2. Select the Visual Web Part project item template and give it a name of ListInspector. Click the Add button.

      Figure 1

      Create a Visual Web Part. C# shown, VB.NET similar for Add Visual Web Part.

  2. Inspect the SPI node for the Web Part named ListInspector. Verify that it contains the SPI files named Elements.xml, ListInspector.cs/vb, ListInspector.webpart, ListInspectorUserControl.ascx and ListInspectorUserControl.ascx.cs (Note: the ListInspectorUserControl.ascx.vb is there but hidden by default).

    Figure 2

    The ListInspector web part in Solution Explorer

  3. Open the Web Part Description file named ListInspector.webpart and examine the XML content inside. You should see the XML already contains two property elements for the Title property and the Description property. Update this Web Part Description file so that it contains a property element and an associated value for each of the name/value pairs in the following table.
    1. ChromeType: TitleAndBorder
    2. Title: List Inspector Web Part
    3. Description: A Web Part which shows all the lists in the current site and allows you to get several of its property values.
    4. CatalogIconImageUrl: _layouts/images/ContosoWebParts/WebPartIcon.gif
    5. TitleIconImageUrl: _layouts/images/ContosoWebParts/WebPartIcon.gif

      XML (Note: Only properties section shown below)

      <properties> <property name="ChromeType" type="string"> TitleAndBorder </property> <property name="Title" type="string"> List Inspector Web Part </property> <property name="Description" type="string"> A Web Part which shows all the lists in the current site and allows you to get several of its property values </property> <property name="CatalogIconImageUrl" type="string"> _layouts/images/ContosoWebParts/WebPartIcon.gif </property> <property name="TitleIconImageUrl" type="string"> _layouts/images/ContosoWebParts/WebPartIcon.gif </property> </properties>
  4. Open the Web Parts Elements.xml and make the following modifications.
    1. Modify the URL attribute of File element to change the .webpart file name to ensure that it is unique. Do this by prepending the text value of "ContosoWebParts_" to the beginning of the URL property value.

      XML

      <?xml version="1.0" encoding="utf-8"?> <Elements xmlns="https://schemas.microsoft.com/sharepoint/" > <Module Name="ListInspector" List="113" Url="_catalogs/wp"> <File Path="ListInspector\ListInspector.webpart" Url="ContosoWebParts_ListInspector.webpart" Type="GhostableInLibrary" > <Property Name="Group" Value="Custom" /> </File> </Module> </Elements>
    2. Change the value for the Group property to "Contoso Web Part".

      XML

      <?xml version="1.0" encoding="utf-8"?> <Elements xmlns="https://schemas.microsoft.com/sharepoint/" > <Module Name="ListInspector" List="113" Url="_catalogs/wp"> <File Path="ListInspector\ListInspector.webpart" Url="ContosoWebParts_ListInspector.webpart" Type="GhostableInLibrary" > <Property Name="Group" Value="Contoso Web Parts" /> </File> </Module> </Elements>
  5. Add an assembly reference to the ContosoWebParts project for the assembly named System.Web.Extensions. This reference is required because developing the new Visual Web Part will involve the UpdatePanel control from ASP.NET AJAX.(Note: to add an assembly reference, right click on the ContosoWebParts project in Solution Explorer and select Add Reference… on the shortcut menu. System.Web.Extensions should be on the .Net tab)
  6. Open the User Control file for the Visual Web Part named ListInspectorUserControl.ascx. You should be able to experiment by moving back and forth between design view and code view. When you are in design view, the designer should be empty at first as no controls or HTML text has been added.
  7. Make sure the User Control is in design view. Also ensure that the Visual Studio toolbox is visible. Look inside the AJAX Extensions section of the toolbox and find the UpdatePanel control as shown in the following screenshot. Drag and drop the UpdatePanel control onto the user control designer.

    Figure 3

    The AJAX Extensions Toolbox

  8. Switch the User Control back to Source code view. Note that the User Control designer added the UpdatePanel control. Your code view should look like what is shown in the following code block.

    ASPX (C# shown, VB.NET identical except for the Control Language line)

    <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Assembly Name="Microsoft.Web.CommandUI, [4-part assembly name]" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, [4-part assembly name]" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, [4-part assembly name]" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, [4-part assembly name]" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, [4-part assembly name]" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ListInspectorUserControl.ascx.cs" Inherits="ContosoWebParts.ListInspector.ListInspectorUserControl" %> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> </asp:UpdatePanel>
  9. Add a ContentTemplate element inside the UpdatePanel element as shown in the following code block. Next, you will copy and paste a pre-provided table layout which contains ASP.NET controls from a text file in your lab folder. Using the Windows Explorer, navigate to c:\Student\Labs\02_VS2010_SPT\StarterFiles. Locate the file named ListInspectorTable.txt. Open the file with NotePad and copy all the text inside to the Windows clipboard. Paste all the text into inside the ContentTemplate element.

    ASPX

    <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <!-- paste text from ListInspectorTable.txt here to create HTML table layout --> </ContentTemplate> </asp:UpdatePanel>
  10. Switch the User Control back into Design view and verify that you can see the table layout.

    Figure 4

    The ListInspector web part in Design view

  11. Now it's time to write some code to bring this Web Part to life. Open the source file named ListInspectorUserControl.ascx.cs/vb. Follow these steps to begin the implementation.
    1. Add a using/imports statement to import the Microsoft.SharePoint namespace
    2. Delete any pre-existing members (properties & methods) from the class definition.
    3. Add a protected field named SelectedListID based on the GUID type.
    4. Add a protected field named UpdateListProperties based on the bool type.
    5. Add a method named lstLists_SelectedIndexChanged using the parameter list shown in the following code block. Note that the ContosoWebParts project will not compile until you add this method implementation because the pre-provided table layout text you pasted in contains a list box named lstLists containing an attribute which attaches it to an event handler named lstLists_SelectedIndexChanged.
    6. Add an implementation of the Page_PreRender method using the parameter list shown in the following code block.

    C#

    using System;
    FakePre-260203e4a7094a3c96af98a8524e2815-caa0280e6d834e8aaacdc907ef5b3bb0FakePre-2b5206015b814d2cbd84c4f5d96b1d1e-5648368250444799a4beed0fb3f00e93FakePre-de539d638d3b412f8ad4d81e9f425779-b92b66776ad4457096075a99bfbb4401using Microsoft.SharePoint;FakePre-e851edca5fd548f8aa78bc0024fbe0f4-05c6bd50f77847cab958609ea8700d29FakePre-e6721e493ba648b4baaef69f3197a965-8093e1d524d241059466dad192bd3a4aFakePre-4b3a0f55a4504221bcd8537e9e1093a8-3df319978c134ca88f5c604195797883FakePre-3184aecde501409b918d6e91ea24e352-df9d06717cd64dcda057dd390b9c779eFakePre-0423e45d50964fd6810c55fc04a70ae2-594d11c2346e472ab0d5a40256d2cf5cFakePre-63989362372e4b15b35858dcf3fb6c2b-ce6b0965a58f4d0caa7ebfd3fb96a1dcFakePre-069b10407b81460e9e93b69f51972715-edbf828168ed4fdab91ff7be26d7810fFakePre-afd0b13f121840b3a9ce2f114678498e-50011a9a82b647db9f2599f4015a85ffFakePre-4e6a0740afb34951b58548dc7c41083f-82c1ff412a2d44229b255d25ac1618d6FakePre-9c16d59816254cac94b45d7cb75d60cb-0c606e65189649e09e8488c8992c64c9FakePre-40d863be9e8447848282d67a1f48b790-b6b89eac9b004da2b4f9f7b521b06196FakePre-afb639f294924543ae7be8f156dfe132-f8e5a56af5744dcb91c500bbb077116bFakePre-66b72dd6ba8d404e81be5b30a0b87b57-237b0dba0ca149d59ec74e79e0f02730FakePre-83fa7aa73a8446e184d23b059548d7c8-8b6ff1eece524eac9ec6e948cc242d40FakePre-cc38b7c6e43a4d449e61a17f33aa2530-66baa095468c4d26b8c6f1206efefb7cFakePre-57d289b2b9074f32b42e0aba9269870e-69ee4ae41eed44d1aaed2039a3cd1882

    VB.NET

    Imports System Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Web.UI.WebControls.WebParts Imports Microsoft.SharePoint Partial Public Class ListInspectorUserControl Inherits UserControl Protected SelectedListID As Guid = Guid.Empty Protected UpdateListProperties As Boolean = False Protected Sub lslLists_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) End Sub Protected Sub Page_PreRender(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.PreRender End Sub End Class
  12. Provide an implementation for lstLists_SelectedIndexChanged as follows.

    C#

    protected void lslLists_SelectedIndexChanged(object sender, EventArgs e) { SelectedListID = new Guid(lstLists.SelectedValue); UpdateListProperties = true; }

    VB.NET

    Protected Sub lslLists_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) SelectedListID = New Guid(lstLists.SelectedValue) UpdateListProperties = True End Sub
  13. Provide an implementation for OnPreRender do the following.
    1. Clear the items from the lstLists control and then add a new list item for each SPList item in the current site. When adding ListItem instances to the ListBox control, use list title as the ListItemText and use list's identifying GUID as the ListItem Value.

      C#

      protected void Page_PreRender(object sender, EventArgs e){ lstLists.Items.Clear(); SPWeb site = SPContext.Current.Web; foreach (SPList list in site.Lists) { ListItem listItem = new ListItem(list.Title, list.ID.ToString()); lstLists.Items.Add(listItem); } }

      VB.NET

      Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender lstLists.Items.Clear() Dim site As SPWeb = SPContext.Current.Web For Each list As SPList In site.Lists Dim listItem As New ListItem(list.Title, list.ID.ToString()) lstLists.Items.Add(listItem) Next End Sub
    2. Since you have cleared the list box and re-added all the list items, you must reapply the selection made by the user. Do this using the following code.

      C#

      protected void Page_PreRender(object sender, EventArgs e) { lstLists.Items.Clear(); SPWeb site = SPContext.Current.Web; foreach (SPList list in site.Lists) { ListItem listItem = new ListItem(list.Title, list.ID.ToString()); lstLists.Items.Add(listItem); } if (SelectedListID != Guid.Empty) { lstLists.Items.FindByValue(SelectedListID.ToString()).Selected = true; } }

      VB.NET

      Protected Sub Page_PreRender(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.PreRender lstLists.Items.Clear() Dim site As SPWeb = SPContext.Current.Web For Each list As SPList In site.Lists Dim listItem As New ListItem( _ list.Title, list.ID.ToString()) lstLists.Items.Add(listItem) Next If SelectedListID <> Guid.Empty Then lstLists.Items.FindByValue(SelectedListID.ToString()).Selected = True End If End Sub
    3. If the UpdateListProperties field contains a value of true, then update all the Label controls on the right-hand side of the table layout to display properties of the selected list. Use the following code block to see the names of the Label controls that need to be updated as well as the SharePoint object model code required.

      C#

      protected void Page_PreRender(object sender, EventArgs e) { lstLists.Items.Clear(); SPWeb site = SPContext.Current.Web; foreach (SPList list in site.Lists) { ListItem listItem = new ListItem(list.Title, list.ID.ToString()); lstLists.Items.Add(listItem); } if (SelectedListID != Guid.Empty) { lstLists.Items.FindByValue(SelectedListID.ToString()).Selected = true; } if (UpdateListProperties) { SPList list = SPContext.Current.Web.Lists[SelectedListID]; lblListTitle.Text = list.Title; lblListID.Text = list.ID.ToString().ToUpper(); lblListIsDocumentLibrary.Text = (list is SPDocumentLibrary).ToString(); lblListIsHidden.Text = list.Hidden.ToString(); lblListItemCount.Text = list.ItemCount.ToString(); lnkListUrl.Text = list.DefaultViewUrl; lnkListUrl.NavigateUrl = list.DefaultViewUrl; } }

      VB.NET

      Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender lstLists.Items.Clear() Dim site As SPWeb = SPContext.Current.Web For Each list As SPList In site.Lists Dim listItem As New ListItem(list.Title, list.ID.ToString()) lstLists.Items.Add(listItem) Next If SelectedListID <> Guid.Empty Then lstLists.Items.FindByValue(SelectedListID.ToString()).Selected = True End If If UpdateListProperties Then Dim list As SPList = _ SPContext.Current.Web.Lists(SelectedListID) lblListTitle.Text = list.Title lblListID.Text = list.ID.ToString().ToUpper() lblListIsDocumentLibrary.Text =(TypeOf list Is SPDocumentLibrary).ToString() lblListIsHidden.Text = list.Hidden.ToString() lblListItemCount.Text = list.ItemCount.ToString() lnkListUrl.Text = list.DefaultViewUrl lnkListUrl.NavigateUrl = list.DefaultViewUrl End If End Sub
    4. Now, you need to add one final piece of code at the very beginning of the OnPreRender implementation to assign a value to the SelectedListID field in cases where the lstLists controls has a selected item but did not generate a postback resulting from a user selecting a different list.

      C#

      protected void Page_PreRender(object sender, EventArgs e) { if ((lstLists.SelectedIndex > -1) & (!UpdateListProperties)) { SelectedListID = new Guid(lstLists.SelectedValue); } lstLists.Items.Clear(); SPWeb site = SPContext.Current.Web; foreach (SPList list in site.Lists) { ListItem listItem = new ListItem(list.Title, list.ID.ToString()); lstLists.Items.Add(listItem); } if (SelectedListID != Guid.Empty) { lstLists.Items.FindByValue(SelectedListID.ToString()).Selected =true; } if (UpdateListProperties) { SPList list = SPContext.Current.Web.Lists[SelectedListID]; lblListTitle.Text = list.Title; lblListID.Text = list.ID.ToString().ToUpper(); lblListIsDocumentLibrary.Text = (list is SPDocumentLibrary).ToString(); lblListIsHidden.Text = list.Hidden.ToString(); lblListItemCount.Text = list.ItemCount.ToString(); lnkListUrl.Text = list.DefaultViewUrl; lnkListUrl.NavigateUrl = list.DefaultViewUrl; } }

      VB.NET

      Protected Sub Page_PreRender(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.PreRender If (lstLists.SelectedIndex > -1) And (Not UpdateListProperties) Then SelectedListID = New Guid(lstLists.SelectedValue) End If lstLists.Items.Clear() Dim site As SPWeb = SPContext.Current.Web For Each list As SPList In site.Lists Dim listItem As New ListItem(list.Title, list.ID.ToString()) lstLists.Items.Add(ListItem) Next If SelectedListID <> Guid.Empty Then lstLists.Items.FindByValue( SelectedListID.ToString()).Selected = True End If If UpdateListProperties Then Dim list As SPList = _ SPContext.Current.Web.Lists(SelectedListID) lblListTitle.Text = list.Title lblListID.Text = list.ID.ToString().ToUpper() lblListIsDocumentLibrary.Text = (TypeOf list Is SPDocumentLibrary).ToString() lblListIsHidden.Text = list.Hidden.ToString() lblListItemCount.Text = list.ItemCount.ToString() lnkListUrl.Text = list.DefaultViewUrl lnkListUrl.NavigateUrl = list.DefaultViewUrl End If End Sub
    5. Build the ContosoWebParts project and make sure there are no compilation errors. If there are errors when running the Build command, find and fix these errors until you can run the Build command without errors.
  14. Now deploy the ListInspector Web Part by right-clicking on the ContosoWebParts project and running the Deploy command which will retract the previous version of the project's solution package and deploy the new one.
  15. In the browser, navigate to the site at https://intranet.contoso.com/sites/lab02 and follow these steps to go through the activation process.
    1. Click Site Actions » Site Settings to navigate to the Site Settings page.
    2. Inside the Site Collection Administration section of the Site Settings page, click on the Site collection features link to navigate to the Site Collection Administration > Features page.
    3. Locate the Custom Web Parts and activate it. If it was already active, then deactivate first and then activate it again. The key point here is that feature activation is what provisions the Web Part Description file with the .webpart extension into the Web Part Gallery. This is required to complete the next step of this exercise.
  16. Now it is time to add a test instance of the ListInspector Web Part. Navigate to the home page default.aspx. Activate the Page ribbon tab and choose Edit Page.

    Figure 5

    Click the Edit Page button on the Page tab of the ribbon

  17. Select the Add a Web Part area in the Left web part zone, to make the additional Page Tools ribbon tab/areas visible. In the Categories (left-hand) section, select the Contoso Web Parts category which should then allow you to see the Web Parts in the right-hand section, one with a title of List Inspector Web Part that you added to ListInspector.webpart. Select the List Inspector Web Part and then click the Add button to add the Web Part instance to the Left Zone of the page. Take the page out of edit mode again by activating the Page ribbon tab (if necessary) and clicking the Stop Editing button. The Web Part should look similar to the one shown in the following screenshot.

    Figure 6

    The List Inspector web part in action

Extra Credit: If you have finished this lab and time remains. You may have noticed that as you select lists on the left side of the screen the right side tends to grow and shrink (which in some cases could grow to a size that effectively “hides” the ability to select lists). Using your knowledge of XML and/or Visual Studio, correct this so that the list box on the left side of the screen has a constant fixed width.

Note:
Once you have tested the ListInspector Web Part and verified it can allow the user to see the properties of each list in the current site, you have completed all the exercises in this lab.