Click here to Skip to main content
16,013,642 members
Articles / Web Development / ASP.NET
Article

Lookup Data Web Control

Rate me:
Please Sign up or sign in to vote.
3.30/5 (8 votes)
28 Jul 2008CPOL1 min read 25K   388   15   1
This is based on key and value pairs that you can select appropriate key and value pair from data source
Image 1

Introduction

This is a composite control and easy to use. I have seen many articles just to improve this control. Many articles suggest Popup window. But I found that many users don't like popup.
I use JavaScript to deal with it so when you select a row from data source it prevents round trip.

Using the code

Just drag and drop the control on the page then assign the control properties and enjoy…!

Page source code:

ASP.NET
 <body style="font-family: Verdana; font-size: 8pt;">
 <form id="form1" runat="server">
 <cc1:LookUpData ID="LookUpData1" runat="server" DataSourceID="SqlDataSource1" 
     KeyControlWidth="40" ValueControlWidth="80">
  <Columns>
   <cc1:Column ColumnType="Key" DataField="Id" HeaderText="Id">
   </cc1:Column>
   <cc1:Column ColumnType="Value" DataField="Name" HeaderText="Name">
    <ItemStyle Width="150px" />
   </cc1:Column>
   <cc1:Column DataField="Age" HeaderText="Age">
    <ItemStyle Width="50px" />
   </cc1:Column>
  </Columns>
 </cc1:LookUpData>
 <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString=
     "<%$ ConnectionStrings:ConnectionString %>" SelectCommand=
     "SELECT * FROM [Users]"></asp:SqlDataSource>
 </form>
</body>

2.JPG

Control code behind:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Web.UI;
using System.ComponentModel;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections;
using System.Drawing.Design;
namespace WebControls.LookupData
{
 [ParseChildren(true),
 DefaultProperty("Key"),
 ToolboxData("<{0}:LookUpData runat="server"></{0}:LookUpData>"),
 ToolboxBitmap(typeof(TextBox))]
 public class LookUpData : DataBoundControl, ICallbackEventHandler
 {
  #region Constructors
  public LookUpData()
  {
  }
  #endregion
  #region Public Properties
  [Category("Columns"), DefaultValue((string)null),
  Editor(typeof(ColumnCollectionEditor), typeof(UITypeEditor)),
  DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
  PersistenceMode(PersistenceMode.InnerProperty)]
  public virtual DataControlFieldCollection Columns
  {
   get
   {
    if (this.columns == null)
    {
     this.columns = new DataControlFieldCollection();
     this.columns.FieldsChanged += new EventHandler(this.OnFieldsChanged);
     if (base.IsTrackingViewState)
     {
      ((IStateManager)this.columns).TrackViewState();
     }
    }
    return this.columns;
   }
  }
  private void OnFieldsChanged(object sender, EventArgs e)
  {
   if (base.Initialized)
   {
    base.RequiresDataBinding = true;
   }
  }
  /// <summary>
  /// Get key from lookup data control.
  /// </summary>
  [ReadOnly(true), Browsable(false)]
  public string Key
  {
   get
   {
    if (keyControl != null)
    {
     return keyControl.Text;
    }
    return null;
   }
  }
  [DefaultValue(40), Category("Appearance")]
  public short KeyControlWidth
  {
   get
   {
    if (this.ViewState["KeyControlWidth"] == null)
     return 40;
    return (short)this.ViewState["KeyControlWidth"];
   }
   set
   {
    this.ViewState["KeyControlWidth"] = value;
    if (keyControl != null)
     keyControl.Width = Unit.Pixel(value);
   }
  }
  /// <summary>
  /// Get value from lookup data control.
  /// </summary>
  [ReadOnly(true), Browsable(false)]
  public string Value
  {
   get
   {
    if (valueControl != null)
    {
     return valueControl.Text;
    }
    return null;
   }
  }
  [DefaultValue(80), Category("Appearance")]
  public short ValueControlWidth
  {
   get
   {
    if (this.ViewState["ValueControlWidth"] == null)
     return 80;
    return (short)this.ViewState["ValueControlWidth"];
   }
   set
   {
    this.ViewState["ValueControlWidth"] = value;
    if (valueControl != null)
     valueControl.Width = Unit.Pixel(value);
   }
  }
  #endregion
  #region Private Methods
  private void searchControl_Click(object sender, EventArgs e)
  {
   DataSourceView dataSource = this.GetData();
   dataSource.Select(new DataSourceSelectArguments(),
    DataSourceCallback);
  }
  public override object DataSource
  {
   get
   {
    return ViewState["DataSource"];
   }
   set
   {
    ViewState["DataSource"] = value;
   }
  }
  private void DataSourceCallback(IEnumerable data)
  {
   string keyHeaderText = GetKeyHeaderText();
   string valueHeaderText = GetValueHeaderText();
   if (data != null & keyHeaderText != null && valueHeaderText != null)
   {
    bool hasResult = false;
    IEnumerator reader = data.GetEnumerator();
    while (reader.MoveNext())
    {
     DataRowView lastReading = reader.Current as DataRowView;
     if (lastReading != null && lastReading[keyHeaderText].ToString() == keyControl.Text)
     {
      valueControl.Text = lastReading[valueHeaderText].ToString();
      hasResult = true;
      break;
     }
    }
    if (!hasResult)
    {
     ClearControls();
     this.hiddenFieldControl.Value = "true";
     this.gridViewControl.DataSource = data;
     this.gridViewControl.DataBind();
    }
    else
    {
     this.hiddenFieldControl.Value = "false";
     this.gridViewControl.DataSource = null;
    }
    keyControl.Focus();
   }
  }
  private void gridViewControl_RowDataBound(object sender, GridViewRowEventArgs e)
  {
   ClientScriptManager scriptManager = this.Page.ClientScript;
   string callbackScript = scriptManager.GetCallbackEventReference(this,
    e.Row.RowIndex.ToString(),
    "ReceiveServerData", "function ReceiveServerData(arg, context){ " +
    "var argArray = arg.split('0$0'); if(argArray.length == 2){" +
    "document.getElementById('" +
        this.keyControl.ClientID + "').value = argArray[0]; " +
    "document.getElementById('" +
        this.valueControl.ClientID + "').value = argArray[1]; } " +
    "document.getElementById('div" +
        this.ClientID + "').style.display = 'none'; } ", true);
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
    e.Row.Attributes.Add("onmouseover", "this.style.color = '" +
        ColorTranslator.ToHtml(Color.Blue) + "'");
    e.Row.Attributes.Add("onmouseout", "this.style.color = '" +
       ColorTranslator.ToHtml(Color.Black) + "'");
    e.Row.Attributes["onclick"] = callbackScript;
    e.Row.Style.Add("cursor", "hand");
   }
  }
  private string GetKeyHeaderText()
  {
   if (columns != null)
   {
    foreach (Column column in Columns)
    {
     if (column.ColumnType == ColumnType.Key)
     {
      return column.HeaderText;
     }
    }
   }
   return null;
  }
  private string GetValueHeaderText()
  {
   if (columns != null)
   {
    foreach (Column column in Columns)
    {
     if (column.ColumnType == ColumnType.Value)
     {
      return column.HeaderText;
     }
    }
   }
   return null;
  }
  private void ClearControls()
  {
   keyControl.Text = string.Empty;
   valueControl.Text = string.Empty;
  }
  #endregion
  #region Override Properties
  public override ControlCollection Controls
  {
   get
   {
    this.EnsureChildControls();
    return base.Controls;
   }
  }
  #endregion
  #region Override Methods
  protected override void CreateChildControls()
  {
   this.keyControl = new TextBox();
   this.keyControl.Width = Unit.Pixel(40);
   this.Controls.Add(this.keyControl);
   this.valueControl = new TextBox();
   this.valueControl.Width = Unit.Pixel(80);
   this.Controls.Add(this.valueControl);
   this.searchControl = new Button();
   this.searchControl.Click += new EventHandler(searchControl_Click);
   this.searchControl.Text = "...";
   this.searchControl.Width = Unit.Pixel(23);
   this.searchControl.Height = Unit.Pixel(23);
   this.Controls.Add(this.searchControl);
   this.gridViewControl = new GridView();
   this.gridViewControl.AutoGenerateColumns = false;
   if (columns != null)
   {
    foreach (Column column in Columns)
    {
     this.gridViewControl.Columns.Add(column);
    }
   }
   this.gridViewControl.AllowPaging = true;
   this.gridViewControl.PageIndexChanging +=
       new GridViewPageEventHandler(gridViewControl_PageIndexChanging);
   this.gridViewControl.RowDataBound +=
       new GridViewRowEventHandler(gridViewControl_RowDataBound);
   this.gridViewControl.CellPadding = 3;
   this.gridViewControl.CellSpacing = 0;
   this.gridViewControl.BorderWidth = 1;
   this.gridViewControl.BorderColor = Color.FromName("#000000");
   this.gridViewControl.BorderStyle = BorderStyle.Solid;
   this.gridViewControl.FooterStyle.BackColor = Color.FromName("#A4DFFC");
   this.gridViewControl.FooterStyle.ForeColor = Color.FromName("#000000");
   this.gridViewControl.RowStyle.BackColor = Color.FromName("#EEEEEE");
   this.gridViewControl.RowStyle.ForeColor = Color.FromName("#000000");
   this.gridViewControl.AlternatingRowStyle.BackColor = Color.FromName("#DDDDDD");
   this.gridViewControl.AlternatingRowStyle.ForeColor = Color.FromName("#000000");
   this.gridViewControl.HeaderStyle.Font.Bold = true;
   this.gridViewControl.HeaderStyle.BackColor = Color.FromName("#BBBBBB");
   this.gridViewControl.HeaderStyle.ForeColor = Color.FromName("#000000");
   this.gridViewControl.PagerStyle.BackColor = Color.FromName("#BBBBBB");
   this.gridViewControl.PagerStyle.ForeColor = Color.FromName("#000000");
   this.gridViewControl.HeaderStyle.Height = Unit.Pixel(20);
   this.Controls.Add(this.gridViewControl);
   this.hiddenFieldControl = new HiddenField();
   this.hiddenFieldControl.Value = "false";
   this.Controls.Add(this.hiddenFieldControl);
  }
  void gridViewControl_PageIndexChanging(object sender, GridViewPageEventArgs e)
  {
   this.gridViewControl.PageIndex = e.NewPageIndex;
   DataSourceView dataSource = this.GetData();
   dataSource.Select(new DataSourceSelectArguments(),
    DataSourceCallback);
  }
  protected override void RenderContents(HtmlTextWriter writer)
  {
   this.AddAttributesToRender(writer);
   writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
   writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
   writer.RenderBeginTag(HtmlTextWriterTag.Table);
   writer.RenderBeginTag(HtmlTextWriterTag.Tr);
   writer.RenderBeginTag(HtmlTextWriterTag.Td);
   this.keyControl.RenderControl(writer);
   this.valueControl.RenderControl(writer);
   this.searchControl.RenderControl(writer);
   writer.RenderEndTag();
   writer.RenderEndTag();
   if (this.hiddenFieldControl.Value == "true")
   {
    ClientScriptManager scriptManager = this.Page.ClientScript;
    string callbackScript = scriptManager.GetCallbackEventReference(this,
     "",
     "ReceiveServerData", "function ReceiveServerData(arg, context){ " +
     "var argArray = arg.split('0$0'); if(argArray.length == 2){" +
     "document.getElementById('" +
         this.keyControl.ClientID + "').value = argArray[0]; " +
     "document.getElementById('" +
         this.valueControl.ClientID + "').value = argArray[1]; } " +
     "document.getElementById('div" +
         this.ClientID + "').style.display = 'none'; } ", true);
    writer.RenderBeginTag(HtmlTextWriterTag.Tr);
    writer.RenderBeginTag(HtmlTextWriterTag.Td);
    writer.RenderBeginTag(HtmlTextWriterTag.Div);
    writer.AddAttribute(HtmlTextWriterAttribute.Id, "div" + this.ClientID);
    StringBuilder styleBuilder = new StringBuilder();
    styleBuilder.Append("z-index: 100;");
    styleBuilder.Append("margin-top: 2px;");
    styleBuilder.Append("position: absolute;");
    styleBuilder.Append("background-color: #FFFFFF;");
    writer.AddAttribute("style", styleBuilder.ToString());
    writer.AddAttribute("onmouseleave", callbackScript);
    this.gridViewControl.RenderControl(writer);
    writer.RenderEndTag();
    writer.RenderEndTag();
    writer.RenderEndTag();
   }
   writer.RenderEndTag();
  }
  #endregion
  #region Private Fields
  private string eventArgument;
  private TextBox keyControl = null;
  private TextBox valueControl = null;
  private Button searchControl = null;
  private GridView gridViewControl = null;
  private DataControlFieldCollection columns;
  private HiddenField hiddenFieldControl = null;
  #endregion
  #region ICallbackEventHandler Members
  public string GetCallbackResult()
  {
   string result = null;
   if (!string.IsNullOrEmpty(eventArgument) && !string.IsNullOrEmpty(this.eventArgument))
   {
    result = gridViewControl.Rows[int.Parse(this.eventArgument)].Cells[0].Text +
     "0$0" + gridViewControl.Rows[int.Parse(this.eventArgument)].Cells[1].Text;
   }
   this.hiddenFieldControl.Value = "false";
   return result;
  }
  public void RaiseCallbackEvent(string eventArgument)
  {
   this.eventArgument = eventArgument;
  }
  #endregion
 }
}

Core of control

As this is a composite control, we need override Ren<code>der method. In fact, the main core function of the control is CreateChildControls. So, whenever the control is initialized, it will call this method after Init and before PreRender events. I have created all my child controls here. The code is self explanatory.

Control without PostBack

I don't want my control to have round trip when user selects a row so I implemented ICallbackEventHandler.

Points of Interest

That sounds interesting...! So, let's start exploring the magic behind this control. It is a composite control. It's a combination of DataBoundControl, ICallbackEventHandler, CollectionEditor, BoundField and others. As it's a composite control, I have derived my class from DataBoundControl class.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalaggiungere funzione di sort Pin
Member 12541603-Apr-11 6:41
Member 12541603-Apr-11 6:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.