|
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using WCPierce.Web.UI;
[assembly:TagPrefix("WCPierce.Web.UI.WebControls", "wcp")]
namespace WCPierce.Web.UI.WebControls
{
/// <summary>
/// AutoCompleteTextBox is similar to the WinForm ComboBox control. As the
/// user types into the box, the enter is "auto-completed" based on values
/// databound to the TextBox by the developer.
/// </summary>
[DefaultProperty("Text"), ToolboxData("<{0}:AutoCompleteTextBox runat=server></{0}:AutoCompleteTextBox>")]
public class AutoCompleteTextBox : System.Web.UI.WebControls.TextBox
{
#region Member Variables
/// <summary>
/// The (relative) path to the AutoCompleteTextBox JavaScript file.
/// </summary>
private string _scriptPath = string.Empty;
/// <summary>
/// For using databinding with your AutoCompleteTextBox
/// </summary>
private object _dataSource = null;
/// <summary>
/// Data returned to the client is in the form of "entry"-newline-
/// "entry"-newline...If you wanted to get cute, we could return in an XML
/// format.
/// </summary>
private static readonly string _FormatString = "{0}\n";
/// <summary>
/// If a ScriptPath isn't specified, check the web.config file for the
/// following key.
/// </summary>
private static readonly string _ScriptPath = "AutoCompleteTextBox.ScriptPath";
/// <summary>
/// CSS Class name for the list item of the dropdownlist.
/// </summary>
private string _listItemCssClass = string.Empty;
/// <summary>
/// CSS Class name for the "hover" effect of the list item of the dropdownlist.
/// </summary>
private string _listItemHoverCssClass = string.Empty;
#endregion
#region Public Properties
/// <summary>
/// The path to the AutoComplete.js file. If you leave it blank, it will
/// automatically look in the web.config for the value under the key
/// "AutoCompleteTextBox.ScriptPath". Should be a path relative to the
/// application root i.e. "~\scripts\AutoCompleteTextBox.js".
/// </summary>
public string ScriptPath
{
get
{
if( _scriptPath != string.Empty )
return ResolveUrl(_scriptPath);
try
{
return ResolveUrl(System.Configuration.ConfigurationSettings.AppSettings[AutoCompleteTextBox._ScriptPath]);
}
catch
{
return null;
}
}
set { _scriptPath = value; }
}
/// <summary>
/// CSS Class name for the list item of the dropdownlist.
/// </summary>
public string ListItemCssClass
{
get { return _listItemCssClass; }
set { _listItemCssClass = value; }
}
/// <summary>
/// CSS Class name for the "hover" effect of the list item of the dropdownlist.
/// </summary>
public string ListItemHoverCssClass
{
get { return _listItemHoverCssClass; }
set { _listItemHoverCssClass = value; }
}
/// <summary>
/// For use with databinding.
/// </summary>
[Bindable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue((string) null)]
public virtual object DataSource
{
get
{
return _dataSource;
}
set
{
if (((value != null) && !(value is IListSource)) && !(value is IEnumerable))
{
throw new ArgumentException("Invalid_DataSource_Type: " + this.ID);
}
_dataSource = value;
}
}
/// <summary>
/// For use with databinding.
/// </summary>
public virtual string DataTextField
{
get
{
object o = this.ViewState["DataTextField"];
if (o != null)
{
return (string)o;
}
return string.Empty;
}
set
{
this.ViewState["DataTextField"] = value;
}
}
/// <summary>
/// For use with databinding.
/// </summary>
public virtual string DataTextFormatString
{
get
{
object o = this.ViewState["DataTextFormatString"];
if (o != null)
{
return (string)o;
}
return string.Empty;
}
set
{
this.ViewState["DataTextFormatString"] = value;
}
}
/// <summary>
/// For use with databinding.
/// </summary>
[DefaultValue("")]
public virtual string DataMember
{
get
{
object o = this.ViewState["DataMember"];
if (o != null)
{
return (string)o;
}
return string.Empty;
}
set
{
this.ViewState["DataMember"] = value;
}
}
#endregion
#region Overrides
/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output">The HTML writer to write out to.</param>
protected override void Render(HtmlTextWriter output)
{
string uId = this.UniqueID;
string newUid = uId.Replace(":", "_");
string divId = newUid + "_Div";
string jsId = newUid + "_Js";
StringBuilder acScript = new StringBuilder();
acScript.Append("<script type=\"text/javascript\">");
acScript.AppendFormat("var {0} = new AutoCompleteTextBox('{1}','{2}');{0}.ListItemClass='{3}';{0}.ListItemHoverClass='{4}';", jsId, newUid, divId, this.ListItemCssClass, this.ListItemHoverCssClass);
acScript.Append("</script>");
Page.RegisterStartupScript(newUid, acScript.ToString());
base.Attributes.Add("AutoComplete", "False");
base.Render(output);
output.Write(String.Format("<div id='{0}'></div>", divId));
}
/// <summary>
/// Register our common scripts and do default PreRendering.
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
this._RegisterCommonScripts();
base.OnPreRender(e);
}
/// <summary>
/// Only fire the OnTextChanged event if this control is the target and it
/// is a Call Back
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
if( Page.Request.Params["__EVENTTARGET"] == this.UniqueID && CallBackHelper.IsCallBack )
{
base.OnTextChanged( e );
}
}
/// <summary>
/// The original idea was to have the Auto Complete Text Box behave like a
/// normal Data Bindable control. But, alas, I couldn't figure that out.
/// Thank you M$ for the databinding code.
/// </summary>
/// <param name="e"></param>
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
IEnumerable ie = DataSourceHelper.GetResolvedDataSource(this.DataSource, this.DataMember);
StringBuilder sb = new StringBuilder();
if( ie != null )
{
bool useTextField = false;
bool useFormatString = false;
string textField = DataTextField;
string formatString = DataTextFormatString;
if( textField.Length != 0 )
{
useTextField = true;
}
if( formatString.Length != 0 )
{
useFormatString = true;
}
foreach( object o in ie )
{
if( useTextField )
{
if( textField.Length > 0)
{
sb.AppendFormat( AutoCompleteTextBox._FormatString, DataBinder.GetPropertyValue(o, textField, formatString) );
}
}
else
{
if( useFormatString )
{
sb.AppendFormat( AutoCompleteTextBox._FormatString, string.Format(formatString, o) );
}
else
{
sb.AppendFormat( AutoCompleteTextBox._FormatString, o.ToString() );
}
} // useTextField
} // foreach
} // ie != null
// Remove trailing '\n'
if( sb.Length > 1 )
sb.Remove(sb.Length-1, 1);
CallBackHelper.Write( sb.ToString() );
}
/// <summary>
/// Perhaps in the future, I will figure out how to make this work. Before
/// you email me with the answer please try using an AutoCompleteTextBox in
/// a DataGrid with ViewState disabled.
/// </summary>
public override void DataBind()
{
// Do Nothing
}
/// <summary>
/// What's the point if the developer turns on AutoPostBack?
/// </summary>
public override bool AutoPostBack
{
get { return false; }
}
#endregion
#region Public Methods
/// <summary>
/// For now, Developer's must call this method to bind to their
/// Auto Complete Text Box.
/// </summary>
public virtual void BindData()
{
this.OnDataBinding(EventArgs.Empty);
}
#endregion
#region Helper Methods
/// <summary>
/// Add a reference to the JavaScript, but only once per page.
/// </summary>
private void _RegisterCommonScripts()
{
if (!this.Page.IsClientScriptBlockRegistered("AutoCompleteTextBox"))
{
StringBuilder script = new StringBuilder();
script.AppendFormat("<script type='text/javascript' src='{0}'></script>", this.ScriptPath);
this.Page.RegisterClientScriptBlock("AutoCompleteTextBox", script.ToString());
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.