blob: 793b1694866dd20229bfb56208cc086d6cc9375d [file] [log] [blame]
using System;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;
using WQD.Core.Controls;
namespace Nexus.Web.Controls
{
/// <summary>
/// Display a list of letters, one of which can be selected at a time,
/// so a client control can filter a list of entries.
/// </summary>
/// <remarks><p>
/// Adapted from http://www.codeproject.com/aspnet/LetterBasedPaging.asp
/// </p></remarks>
///
public class LetterFilter : FindControl
{
/// <summary>
/// Document token representing match all entries.
/// </summary>
public const string ALL = "[*]";
/// <summary>
/// Document the attribute name for the initial letter by which to filter.
/// </summary>
public const string ITEM_INITIAL = "initial";
/// <summary>
/// Provide a key under which to store the selected letter in ViewState.
/// </summary>
///
public const string LETTER_KEY = "_Letter";
/// <summary>
/// Document the wildcard character used by SQL queries.
/// </summary>
public const string WILDCARD = "%";
/// <summary>
/// Signal that input is ready to submit,
/// passing the ITEM_INTIIAL value as FindArgs.
/// </summary>
///
public event EventHandler View_Filter;
/// <summary>
/// List the letters that can selected.
/// </summary>
///
protected Repeater letters;
/// <summary>
/// Provide a private field to cache the LetterFilter property.
/// </summary>
///
private string _Letter;
/// <summary>
/// Store the current letter by which client is to filter.
/// </summary>
/// <remarks><p>
/// The value is stored by ID in ViewState
/// so that more than one LetterFilter can be used by the same parent control.
/// </p></remarks>
///
public string Letter
{
get
{
if (_Letter == null) _Letter = ViewState[ID + LETTER_KEY] as string;
return _Letter;
}
set
{
_Letter = value;
ViewState[ID + LETTER_KEY] = value;
// Bind the datasource so that Letter change is reflected
letters.DataBind();
}
}
/// <summary>
/// Provide a key under which to store the DataTable in ViewState.
/// </summary>
///
private string LETTER_TABLE_KEY = "_LetterData";
/// <summary>
/// Provide a private field to cache the LetterTable property.
/// </summary>
///
private DataTable _LetterTable;
/// <summary>
/// Store the DataTable containing our letters.
/// </summary>
///
public DataTable LetterTable
{
get
{
if (_LetterTable == null) _LetterTable = ViewState[ID + LETTER_TABLE_KEY] as DataTable;
return _LetterTable;
}
set
{
_LetterTable = value;
ViewState[ID + LETTER_TABLE_KEY] = value;
}
}
/// <summary>
/// Provide the name of the item command to fire when the linkbutton for a letter is clicked.
/// </summary>
///
protected const string FILTER_CMD = "filter";
/// <summary>
/// Identify the linkbutton that will contain the letter in each repeater cell.
/// </summary>
///
protected const string LETTER_ID = "letter";
/// <summary>
/// Identify the column in our DataTable that holds the letters.
/// </summary>
///
protected const string LETTER_COLUMN = "Letter";
/// <summary>
/// Handle the "Filter" by new letter command,
/// passing NULL if "ALL" is selected.
/// </summary>
///
protected void letters_ItemCommand(object source, RepeaterCommandEventArgs e)
{
// Handle the "Filter" new record command
if (e.CommandName == FILTER_CMD)
{
// Set the new Letter selection
Letter = (string) e.CommandArgument;
// Raise the "Filter" event so that client can update its list.
if (View_Filter != null)
{
string letter = Letter;
if (ALL.Equals(letter)) letter = null;
string letter2 = letter + WILDCARD;
IDictionary criteria = new Hashtable(1);
criteria.Add(ITEM_INITIAL, letter2);
FindArgs a = new FindArgs(e, criteria);
View_Filter(source, a);
}
}
}
/// <summary>
/// Called when an item in the letters repeater control is data bound to a source.
/// </summary>
protected void letters_ItemDataBound(object source, RepeaterItemEventArgs e)
{
// Retrieve the row of data that is to be bound to the repeater
DataRowView data = (DataRowView) e.Item.DataItem;
// If the letter we are binding to the current repeater control item is
// the same as the one currently selected, than disable it so the user
// knows which one was selected.
if ((string) data[0] == Letter)
{
LinkButton cmd = (LinkButton) e.Item.FindControl(LETTER_ID);
cmd.Enabled = false;
}
}
/// <summary>
/// Create a new DataTable from the list of letters provided,
/// and store a referance to the newly create data table for use on post back.
/// </summary>
/// <param name="input">List of letters to present as commands</param>
private void LetterTable_Init(IList input)
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn(LETTER_COLUMN, typeof (string)));
for (int i = 0; i < input.Count; i++)
{
DataRow dr = dt.NewRow();
dr[0] = input[i];
dt.Rows.Add(dr);
}
LetterTable = dt;
Letter = null;
}
/// <summary>
/// Bind the letters array to the repeater control,
/// set the default letter,
/// so that the letters are ready to present.
/// </summary>
///
public override bool Open()
{
if (LetterTable == null)
{
// Default to A-Z
string[] input = {
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z", ALL
};
LetterTable_Init(input);
}
letters.DataSource = LetterTable.DefaultView;
string current = Letter;
if (current == null) Letter = ALL;
return true;
}
/// <summary>
/// Bind the letters array to the repeater control,
/// set the default letter,
/// so that the letters are ready to present.
/// </summary>
///
public bool Open(IList letters)
{
LetterTable_Init(letters);
return Open();
}
/// <summary>
/// Pass our DataGrid instance to base member.
/// </summary>
///
private void Page_Init()
{
letters.ItemCommand += new RepeaterCommandEventHandler(this.letters_ItemCommand);
letters.ItemDataBound += new RepeaterItemEventHandler(this.letters_ItemDataBound);
}
/// <summary>
/// Handle the page Load event.
/// </summary>
/// <param name="sender">Event source</param>
/// <param name="e">Runtime parameters</param>
///
private void Page_Load(object sender, EventArgs e)
{
Open();
}
#region Web Form Designer generated code
/// <summary>
/// Generated method for Designer support.
/// </summary>
/// <param name="e">Runtime parameters</param>
///
protected override void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
Page_Init();
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new EventHandler(this.Page_Load);
}
#endregion
}
}