Step by Step - Creating Connected SharePoint Web Parts using IWebPartField interface and using Editor Part and User Controls

I was eagerly waiting for the release of VSeWSS version 1.2 for VS 2008. Without it developing custom SharePoint applications in VS 2008 was like nightmare. Let us explore it by creating connected web parts. This time we will create connected Web Parts similar to the one we have created earlier.

Things we will do here:

  1. We will use standard IWebPartField interface.
  2. We will use Categories and Products table from Northwind database as the data sources. We will use a dropdown in the provider web part to show all categories and we will use a GridView in the Consumer Web Part to show the Products data.
  3. We will use Editor Part for changing the properties (font color in the GridView) of the Consumer Web Part.
  4. We will use Web User Controls for both the Web Parts and also the Editor Part.

Step 1:

Start VS 2008 and select new Project and select Visual C#>SharePoint>Web Part. Change the name as ContosoStandardConWP. In the Solution explorer select the folder Webpart1 and delete it. Add reference of System.Drawing to the Project.

Right click on the project and select Add>New Item. Select SharePoint>Web Part and change the name ContosoStandardConProviderWP and similarly add another Web Part and name it as ContosoStandardConConsumerWP.

Again right click on the project and select Add>New Item. Select Code>Class. Change the name as ContosoStandardConEP.cs.

Right click on the project and select Add>New Folder. Name it as Templates. Similarly create another folder under Templates and name it controltemplates. Right click on controltemplates and select Add>New Item. In the new item window select General and Text File. Change the name of the Text File as ContosoStandardConProviderUC.ascx. Similarly add 2 more files and change the name as ContosoStandardConConsumerUC.ascx and ContosoStandardConEPUC.ascx.

Step 2:

Now open the ContosoStandardConProviderUC.ascx file and from the Toolbox add a DropDownList into it. Similarly add one GridView into ContosoStandardConConsumerUC.ascx and another DropDownList into ContosoStandardConEPUC.ascx. Keep the name of these controls as default. You may find that the design mode is not working for these User Controls. If required you can create a separate application (web site) and can add web user control there and can add and see all these controls in design mode and can copy the HTML from there to our project.

Step 3:

Open ContosoConProviderWP.cs file and add these using statements:

using System.Data;

using System.Data.SqlClient;

using System.ComponentModel;

Change the class statement from:

public class ContosoStandardConProviderWP : System.Web.UI.WebControls.WebParts.WebPart

to

public class ContosoStandardConProviderWP : System.Web.UI.WebControls.WebParts.WebPart, IWebPartField

Before the default constructor add the following lines:

DropDownList CatList;

        UserControl userControl;

        int CatListVal = 0;

        public int CategoryID

        {

            get

            {

                return this.CatListVal;

            }

        }

        [ConnectionProvider("Web part Connection Provider")]

        public IWebPartField GetWPConnectFieldProvider()

        {

            return this;

        }

        public void GetFieldValue(FieldCallback callback)

        {

            callback.Invoke(this.CatListVal);

        }

        public PropertyDescriptor Schema

        {

            get

            {

                return TypeDescriptor.GetProperties(this)["Web part Connection Provider"];

            }

        }

Step 4:

Replace the content of the CreateChildControls method with the following:

            userControl = (UserControl)Page.LoadControl(@"/_controltemplates/ContosoStandardConProviderUC.ascx");

            CatList = (DropDownList)userControl.FindControl("DropDownList1");

            SqlConnection newSqlConnection = new SqlConnection();

            SqlCommand newSqlCommand = new SqlCommand("Select CategoryID,CategoryName from categories", newSqlConnection);

            newSqlCommand.CommandType = System.Data.CommandType.Text;

            newSqlConnection.ConnectionString = "Integrated Security=True;Initial Catalog=Northwind;Data Source=pranab-sec";

            newSqlConnection.Open();

            CatList.DataValueField = "CategoryID";

            CatList.DataTextField = "CategoryName";

            CatList.AutoPostBack = true;

            CatList.DataSource = newSqlCommand.ExecuteReader();

            CatList.DataBind();

            CatList.SelectedIndexChanged += new EventHandler(CatList_SelectedIndexChanged);

            Controls.Add(userControl);

            newSqlConnection.Close();

After CreateChildControls method add these lines:

        void CatList_SelectedIndexChanged(object sender, EventArgs e)

        {

            this.CatListVal = int.Parse(this.CatList.SelectedValue);

        }

        protected override void Render(HtmlTextWriter writer)

        {

            EnsureChildControls();

            this.userControl.RenderControl(writer);

        }

       

Step 5:

Open ContosoConConsumerWP.cs file and add these using statements:

using System.Data;

using System.Data.SqlClient;

using System.Collections.Generic;

using System.Drawing;

Change the class statement from:

public class ContosoStandardConConsumerWP : System.Web.UI.WebControls.WebParts.WebPart

to

public class ContosoStandardConConsumerWP : System.Web.UI.WebControls.WebParts.WebPart,IWebEditable

Before the default constructor add the following lines:

protected int selectedCatID;

        protected GridView NewDataGrid;

        protected UserControl userControl;

        protected string SqlQuery = "Select ProductID,ProductName,UnitPrice from Products";

        [WebBrowsable(false), Personalizable(true)]

        public string DisplayFontName

        {

            get;

            set;

        }

        [ConnectionConsumer("Web Part Consumer")]

        public void GetWPConnectedProviderInterface(IWebPartField connectProvider)

        {

            FieldCallback callback = new FieldCallback(ReceiveField);

            connectProvider.GetFieldValue(callback);

        }

        public void ReceiveField(object objField)

        {

            if (objField != null)

            {

                this.selectedCatID = (int)objField;

                if (this.selectedCatID != 0)

                    this.SqlQuery += " where CategoryID = " + this.selectedCatID.ToString();

            }

        }

        protected override void OnPreRender(EventArgs e)

        {

            SqlConnection newSqlConnection = new SqlConnection();

            SqlCommand newSqlCommand = new SqlCommand(this.SqlQuery, newSqlConnection);

            newSqlCommand.CommandType = System.Data.CommandType.Text;

            newSqlConnection.ConnectionString = "Integrated Security=True;Initial Catalog=Northwind;Data Source=pranab-sec";

            newSqlConnection.Open();

            NewDataGrid.DataSource = newSqlCommand.ExecuteReader();

            NewDataGrid.DataBind();

            newSqlConnection.Close();

            newSqlConnection.Dispose();

            newSqlCommand.Dispose();

            this.Controls.Add(userControl);

        }

Step 6:

Replace the content of CreateChildControls method with the following:

            userControl = (UserControl)Page.LoadControl(@"/_controltemplates/ContosoStandardConConsumerUC.ascx");

            NewDataGrid = (GridView)userControl.FindControl("GridView1");

            Style myStyle = new Style();

            myStyle.ForeColor = Color.Black;

            if (DisplayFontName != null)

            {

                switch (DisplayFontName.ToString())

                {

                    case "Red":

                        myStyle.ForeColor = Color.Red;

                        break;

                    case "Blue":

                        myStyle.ForeColor = Color.Blue;

                        break;

                    case "Green":

                        myStyle.ForeColor = Color.Green;

                        break;

  default:

                        myStyle.ForeColor = Color.Black;

                        break;

                }

            }

            NewDataGrid.ApplyStyle(myStyle);

After CreateChildControls method add these lines:

protected override void Render(HtmlTextWriter writer)

        {

            EnsureChildControls();

            this.userControl.RenderControl(writer);

        }

        EditorPartCollection IWebEditable.CreateEditorParts()

        {

            List<EditorPart> editors = new List<EditorPart>();

            editors.Add(new ContosoStandardConEP(this.ID));

            return new EditorPartCollection(editors);

        }

        object IWebEditable.WebBrowsableObject

        {

            get { return this; }

        }

Step 7:

Open up ContosoStandardConEP.cs file and change the entire content as:

using System;

using System.Collections.Generic;

using System.Text;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.WebControls;

using System.Web.UI;

namespace ContosoStandardConWP

{

    class ContosoStandardConEP : EditorPart

    {

        DropDownList ddlDisplayFont;

        UserControl userControlToolPart;

        public ContosoStandardConEP(string webPartID)

        {

            this.ID = "ContosoStandardConConsumerWP" + webPartID;

            this.Title = "Select Font Color";

            this.Description = "Select Font Color for Products";

        }

        protected override void CreateChildControls()

        {

            userControlToolPart = (UserControl)Page.LoadControl(@"/_controltemplates/ContosoStandardConEPUC.ascx");

            ddlDisplayFont = (DropDownList)userControlToolPart.FindControl("DropDownList1");

           

            //You can make the item adding part dynamic

            ddlDisplayFont.Items.Add("Red");

            ddlDisplayFont.Items.Add("Blue");

            ddlDisplayFont.Items.Add("Green");

            ddlDisplayFont.Items.Add("None");

            //////////////////////////////////////

           

            Controls.Add(userControlToolPart);

        }

        public override bool ApplyChanges()

        {

            EnsureChildControls();

            ContosoStandardConConsumerWP webPart = WebPartToEdit as ContosoStandardConConsumerWP;

            if (webPart != null)

            {

                webPart.DisplayFontName = ddlDisplayFont.SelectedValue;

            }

            return true;

        }

        public override void SyncChanges()

        {

            EnsureChildControls();

            ContosoStandardConConsumerWP webPart = WebPartToEdit as ContosoStandardConConsumerWP;

            if (webPart != null)

                ddlDisplayFont.SelectedValue = webPart.DisplayFontName;

        }

    }

}

Step 8:

Right click on the project once again and go to properties and in the Debug tab and Start Browser with URL add the destination site’s URL. Now deploy the application from Build>Deploy menu and open the URL in a browser.

Step 9:

In the site click on Site Actions>Edit Page and click on Add a Web Part in any Web Part Zone. This will open up the Web Part gallery and under Misceleneous section you will find ContosoStandardConProviderWP and ContosoStandardConConsumerWP Web Parts. Select the Web Parts and those will be added to the Web Part Zone. Click on the Edit option at ContosoStandardConConsumerWP and select Connections>Get Web Part Consumer From> ContosoStandardConProviderWP. Now if you exit the edit mode you can see 2 Web Parts. If you select a value from the categories, corresponding products will be shown. Again if you modify the consumer Web Part you can find an option in the Web Part task pane to change the font color of the Web Part. Select a new value and you can see it changes the color.