Saturday, May 29, 2010

Creating a Facebook like Add Contacts type ahead (auto complete) control in ASP.Net

It once came out to me that I wanted to create a facebook like add contacts control where you can add contacts in the messages section of the face book by using .net framework's auto complete feature.

Just wanted to share this, so that anyone working on .Net and wanted to have a control like that would work on anything like this.

I created a User Control in the application and modified it according to my needs. You may modify any functionality you want for this user control.

Main Theme:

Main Theme is that we need to create a panel. Inside the panel, there should be one textbox with autocomplete extender and one Label for the text box and one repeater control to add the elements, that have been suggested by the user control....

Source code of the control would be like this:

ASCX Page:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MultiAutoComplete.ascx.cs"
Inherits="UC_MultiAutoComplete" %>
<table id="tblMain" runat="server" cellpadding="0" cellspacing="0" border="0" align="center">
<tr class="dataEntryTR">
<td>
<asp:Label ID="lblLabel" runat="server"></asp:Label>
</td>
<td>
<asp:Panel ID="pnlMultiAutoComplete" runat="server">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="MultiAutoComplete" onfocus="document.getElementById('<%= txtAC.ClientID %>').focus();">
<asp:Repeater ID="rptDB" runat="server" OnItemDataBound="rptDB_ItemDataBound">
<ItemTemplate>
<div class="MultiACdiv" style="width: <%# (DataBinder.Eval(Container.DataItem, "Name").ToString().Length * 10) %>px;">
<%# DataBinder.Eval(Container.DataItem, "Name") %>&nbsp;<asp:ImageButton ID="ibtnCross"
runat="server" AlternateText="del" ImageAlign="absmiddle" ImageUrl="~/images/Buttons/cross_button.jpg"
BorderWidth="0" ToolTip='<%# DataBinder.Eval(Container.DataItem, "MainID") %>'
EnableTheming="false" OnClick="ibtnCross_Click" CausesValidation="false" />
</div>
</ItemTemplate>
</asp:Repeater>
<ajaxToolkit:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" TargetControlID="txtAC"
MinimumPrefixLength="2" CompletionInterval="1000" CompletionListCssClass="autocomplete_completionListElement"
CompletionListItemCssClass="autocomplete_listItem" CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
EnableCaching="true" DelimiterCharacters=";">
</ajaxToolkit:AutoCompleteExtender>
<input type="hidden" id="txtID" runat="server" value='<%# _ControlID %>' />
<asp:TextBox ID="txtAC" runat="server" OnTextChanged="txtAC_TextChanged" AutoPostBack="true"
SkinID="multiACtxt"></asp:TextBox>
</td>
</tr>
</table>
</asp:Panel>
</td>
</tr>
</table>

CS Page:

using System;
using System.Data;
using System.Web.UI.WebControls;
using System.ComponentModel;

public partial class UC_MultiAutoComplete : System.Web.UI.UserControl
{
#region Private Variables
private DataTable _DataSource;
private string _DeleteConfirmText;
private string _AutoCompleteServiceMethod;
protected string _ControlID;
#endregion

#region Properties
public string width
{
get { return tblMain.Style["width"].ToString(); }
set { tblMain.Style.Add("width", value); }
}
public string height
{
get { return tblMain.Style["height"].ToString(); }
set { tblMain.Style.Add("height", value); }
}
public string align
{
get { return tblMain.Attributes["align"].ToString(); }
set { tblMain.Attributes.Add("align", value); }
}
public string LabelText
{
get { return lblLabel.Text; }
set { lblLabel.Text = value; }
}
///
/// Gets or Sets the Datasource of the repeater.
/// Must be a DataTable object with one column of name "Name"
///

public DataTable DataSource
{
get { return _DataSource; }
set { _DataSource = value; }
}
public string DeleteConfirmText
{
get { return _DeleteConfirmText; }
set { _DeleteConfirmText = value; }
}
public string AutoCompleteServiceMethod
{
get { return _AutoCompleteServiceMethod; }
set { _AutoCompleteServiceMethod = value; }
}
public string ControlMainID
{
get { return _ControlID; }
set { _ControlID = value; }
}
#endregion

public delegate void MultiAutoCompleteEventHandler(object sender, MultiAutoCompleteEventArgs e);
public event MultiAutoCompleteEventHandler MAC_TextChanged;
protected virtual void MAC_OnTextChanged(MultiAutoCompleteEventArgs e)
{
MAC_TextChanged(this, e);
}

public event MultiAutoCompleteEventHandler MAC_Delete;
protected virtual void MAC_OnDelete(MultiAutoCompleteEventArgs e)
{
MAC_Delete(this, e);
}

protected void Page_Init(object sender, EventArgs e)
{
AutoCompleteExtender1.ServiceMethod = _AutoCompleteServiceMethod;
}

protected void Page_Load(object sender, EventArgs e)
{
txtAC.Focus();
}

public override void DataBind()
{
base.DataBind();
if (_DataSource == null)
{
//MessageBox.Show("Data Source is not assigned...", Page);
return;
}
rptDB.DataSource = _DataSource;
rptDB.DataBind();
txtAC.Text = "";
}

protected void ibtnCross_Click(object sender, EventArgs e)
{
ImageButton ibtn = (ImageButton)sender;
MAC_OnDelete(new MultiAutoCompleteEventArgs(txtID.Value, ibtn.ToolTip, txtAC.Text));
}

protected void rptDB_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Header && e.Item.ItemType != ListItemType.Footer)
{
ImageButton ibtn = (ImageButton)e.Item.FindControl("ibtnCross");
ibtn.Attributes.Add("onclick", "return window.confirm('" + _DeleteConfirmText + "');");
}
}

protected virtual void txtAC_TextChanged(object sender, EventArgs e)
{
MAC_OnTextChanged(new MultiAutoCompleteEventArgs(txtID.Value, txtAC.Text));
}
}

#region class MultiAutoCompleteEventArgs
public class MultiAutoCompleteEventArgs : EventArgs
{
#region Private Variables
private string _ID;
private string _ItemID;
private string _Text;
#endregion

#region Properties
public string ID
{
get { return _ID; }
}
public string ItemID
{
get { return _ItemID; }
}
public string Text
{
get { return _Text; }
}
#endregion

public MultiAutoCompleteEventArgs(string __ID, string __Text) { _ID = __ID; _Text = __Text; }
public MultiAutoCompleteEventArgs(string __ID, string __ItemID, string __Text) { _ID = __ID; _ItemID = __ItemID; _Text = __Text; }
}
#endregion