Sunday, January 4, 2009

Custom GridView Field For SharePoint LookUp Column

In Sharepoint When retrieve data using web service, there is need for customization during display in GridView. There are two ways to do this.

1. First Way

Use Template Column of GridView. Write Inline coding to Format data.

For Example .

In Codebehind file Write Following Function.

To Fetch data using web service.

public DataTable GetData()
{     

DataTable dt = new DataTable();
Lists lst = new Lists();
lst.Url = "
/_vti_bin/lists.asmx";'>http://<your site>/_vti_bin/lists.asmx";
lst.Credentials = new System.Net.NetworkCredential("test", "test"); 
XmlNode result =lst.GetListItems("Orders", String.Empty, null, null, int.MaxValue.ToString(), null, string.Empty); 
System.IO.StringReader read = new System.IO.StringReader(result.OuterXml); 
DataSet dst = new DataSet(); 
dst.ReadXml(read); 
if (dst.Tables.Count == 2 && Convert.ToInt32(dst.Tables[0].Rows[0]["ItemCount"].ToString()) > 0)
        {
            dt = dst.Tables[1];
        }
        else
        {
            dt.Columns.Add(new DataColumn("ows_CustomerID",typeof(string)));
        }
        return dt;

    }

// Enum For Display Mode of LookUpField.

public enum Mode
{
        ID,
        Value,
        All
};

// Function that format data (This Fuction must be Public or Proctected)

protected string GetLookupValue(string value,Mode LookUpDisplayMode)
    {
        string returnVal = String.Empty;
        string[] str;
        try
        {
            switch (LookUpDisplayMode)
            {
                case Mode.All:
                    returnVal = value;
                    break;
                case Mode.ID:
                    str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                    returnVal = str[0];
                    break;
                case Mode.Value:
                    str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                    returnVal = str[1];
                    break;
            }
        }
        catch
        {
        }
        return returnVal;
    }

And in ASPX Page.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" >
        <Columns>                     
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.ID) %>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.Value) %>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.All) %>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
</asp:GridView>
   

2. Other Way

This way is create custom DataBoundField that inherits from BoundField.This is required one time coding as well as avoid inline coding.

Put following class in either App_Code or create class library and use it any application you want.

//LookupField Class

public class LookupField : BoundField
    {
        public enum Mode { ID, Value, All};

        public LookupField()
        {
}

        public Mode LookUpDisplayMode
        {
            get;
            set;
        }

        protected override string FormatDataValue(object dataValue, bool encode)
        {
            dataValue = GetLookupValue(dataValue.ToString());
            return base.FormatDataValue(dataValue, encode);
        }

        protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
        {
            if(rowState == DataControlRowState.Normal || rowState == DataControlRowState.Selected || rowState == DataControlRowState.Alternate)
                base.InitializeDataCell(cell, rowState);           
            else
            {                              
                TextBox txt = new TextBox();               
                cell.Controls.Add(txt);
                txt.DataBinding += new EventHandler(OnDataBindField);               
            }           
        }

        protected override DataControlField CreateField()
        {
            return new LookupField();
        }

        protected override void OnDataBindField(object sender, EventArgs e)
        {
            Control c = sender as Control;
            if(c is TableCell)
                base.OnDataBindField(sender, e);
            else if (c is TextBox)
            {
                string val=  GetLookupValue(this.GetValue(c.NamingContainer).ToString());
                ((TextBox)c).Text = val;
            }
        }
        private string GetLookupValue(string value)
        {
            string returnVal = String.Empty;
            string[] str;
            try
            {
                switch (LookUpDisplayMode)
                {
                    case Mode.All:
                        returnVal = value;
                        break;
                    case Mode.ID:
                        str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                        returnVal = str[0];
                        break;
                    case Mode.Value:
                        str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                        returnVal = str[1];
                        break;
                }
            }
            catch
            {
            }
            return returnVal;
        }
    }

// ASPX Page.
Register Control
<%@ Register TagPrefix="CC" Assembly="App_Code" Namespace="LookupFields" %>

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
            AutoGenerateEditButton="true" onrowediting="GridView1_RowEditing">
        <Columns>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="ID" HeaderText="CustomerID"></CC:LookupField>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="Value" HeaderText="CustomerValue"></CC:LookupField>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="All" HeaderText="Customer"></CC:LookupField>

</asp:GridView>

In above two way use following code to bind GridView.

//ASPX Page

protected void Page_Load(object sender, EventArgs e)
   {
       if (!Page.IsPostBack)
       {
           GridView1.DataSource = GetData();
           GridView1.DataBind();
       }
   }

Note: Implementation of custom LookupField is not complete. You may required to add or override few more function in order to work with diffrent mode of GridView Row. (Row Selection , Editing etc).

Please give me your comment.

2 comments:

John Frag said...

My current project requires ability to display choice column value via color or image associated with a choice

But Sharepoint standard packaged misses that control

I am looking for available solutions on market

I came across


http://amazepoint.com/Products/VisualChoiceColumn/Overview.aspx


Does anybody has experiece using it?

dotnetstep said...

I never used VisualChoiceColumn. If you want to create your own column than you can creare custom
column.
http://vspug.com/nicksevens/2007/08/31/create-custom-field-types-for-sharepoint/