Demonstrations > Client state
Client state
Tip: Try keeping the DbCombo drop-down open while changing the category and supplier drop-downs. DbCombo will react to the changes and get the updated data-set.
The code...
The code for this page is a little long, but I've included some comments to show you what's being done:
The first section simply draws the table, includes the four WebControls, and includes the DbCombo control. Notice on each of the WebControls we call our UpdateCombo() javascript function. This will tell DbCombo that the state has changed.
<p>
<table>
<tr>
<td>
<asp:CheckBox Runat="server"
Text="Limit results to supplier:"
ID="SupplierCheckBox"
onclick="UpdateCombo();"/>
</td>
<td>
<asp:DropDownList
Runat="server"
ID="SupplierDropDown"
onchange="UpdateCombo();" />
</td>
</tr>
<tr>
<td>
<asp:CheckBox Runat="server"
Text="Limit results to category:"
ID="CategoryCheckBox"
onclick="UpdateCombo();"/>
</td>
<td>
<asp:DropDownList Runat="server"
ID="CategoryDropDown"
onchange="UpdateCombo();" />
</td>
</tr>
<tr>
<td>Select your product:</td>
<td>
<DbCombo:DbCombo runat="server" ID="Combo1"
ClientStateFunction="StateFunction()"
OnGetDownLevelState="DownLevelState"
CloseResultsOnBlur="false" />
</td>
</tr>
</table>
</p>
Next is the javascript function we attached to the change events of the WebControls earlier. This
calls the DbComboStateChanged function, using the UniqueID of the Combo control as a parameter.
<script language=javascript>
function UpdateCombo()
{
if (typeof(DbComboServerExists)!='undefined')
DbComboStateChanged('<%# Combo1.UniqueID %>');
}
</script>
Next is our javascript state function. This is referenced by the ClientStateFunction="StateFunction()"
attribute of our DbCombo tag. This wraps several bits of information about the page state in a javascript
"Object" object, and returns it.
<script language=javascript>
function StateFunction()
{
var state = new Object();
categoryDropDown = document.all["<%# CategoryDropDown.UniqueID %>"];
categoryCheckBox = document.all["<%# CategoryCheckBox.UniqueID %>"];
supplierDropDown = document.all["<%# SupplierDropDown.UniqueID %>"];
supplierCheckBox = document.all["<%# SupplierCheckBox.UniqueID %>"];
if (categoryCheckBox.checked){
state["ConstrainCategory"]="true";
state["CategoryID"]=
categoryDropDown[categoryDropDown.selectedIndex].value;
}
else
state["ConstrainCategory"]="false";
if (supplierCheckBox.checked){
state["ConstrainSupplier"]="true";
state["SupplierID"]=
supplierDropDown[supplierDropDown.selectedIndex].value;
}
else
state["ConstrainSupplier"]="false";
return state;
}
</script>
Next is our Page_Load server code block. This simply populates our two conventional
drop-down's with data from the Categories and Suppliers tables. Note we also do a
Page.DataBind() to Bind our <%# %> blocks.
<script runat=server>
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
if (!Page.IsPostBack)
{
DataSet dataset=new DataSet();
SqlConnection conn = new SqlConnection("your-connection-string");
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand =
new SqlCommand("SELECT * FROM Categories", conn);
adapter.Fill(dataset);
conn.Close();
CategoryDropDown.DataSource=dataset;
CategoryDropDown.DataTextField="CategoryName";
CategoryDropDown.DataValueField="CategoryID";
CategoryDropDown.DataBind();
dataset=new DataSet();
adapter.SelectCommand =
new SqlCommand("SELECT * FROM Suppliers", conn);
adapter.Fill(dataset);
conn.Close();
SupplierDropDown.DataSource=dataset;
SupplierDropDown.DataTextField="CompanyName";
SupplierDropDown.DataValueField="SupplierID";
SupplierDropDown.DataBind();
}
Page.DataBind();
}
</script>
Next is our DbCombo server method. It first inspects the clientState Hashtable. We have populated
this earlier in Javascript, and DbCombo has converted it to a Hashtable for us. Using this we create
an SQL fragment which is then appended to a simple SQL statement. The SQL statement is used to create
a DataSet, which is returned.
<script runat=server>
[Cambro.Web.DbCombo.ResultsMethod(true)]
public static object DbComboMethod(
Cambro.Web.DbCombo.ServerMethodArgs args)
{
string extraWhereClause = "";
if (args.ClientState!=null)
{
if (
args.ClientState["ConstrainCategory"] != null &&
args.ClientState["ConstrainCategory"].ToString()=="true"
)
{
extraWhereClause += " AND CategoryID = " +
int.Parse(args.ClientState["CategoryID"].ToString()) + " ";
}
if (
args.ClientState["ConstrainSupplier"] != null &&
args.ClientState["ConstrainSupplier"].ToString()=="true"
)
{
extraWhereClause += " AND SupplierID = " +
int.Parse(args.ClientState["SupplierID"].ToString()) + " ";
}
}
DataSet dataset=new DataSet();
SqlConnection conn = new SqlConnection("your-connection-string");
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(@"
SELECT TOP "+args.Top+@"
ProductName AS DbComboText,
ProductID AS DbComboValue
FROM Products WHERE
ProductName LIKE @Query "+extraWhereClause+@"
ORDER BY ProductName", conn);
adapter.SelectCommand.Parameters.Add("@Query", args.Query+"%");
adapter.Fill(dataset);
conn.Close();
return dataset;
}
</script>
This server code function is only necessary for down-level browser compatibility.
It is referenced in the DbCombo tag by the OnGetDownLevelState="DownLevelState" attribute.
As you can see, it does the same job as the Javascript state function we saw earlier, but
using PostBack data.
<script runat=server>
protected Hashtable DownLevelState(DbCombo sender)
{
//This function is only used in down-level browser mode.
//If you know all browsers will be IE5+, this function may be
//omitted.
Hashtable state = new Hashtable();
if (CategoryCheckBox.Checked){
state["ConstrainCategory"]="true";
state["CategoryID"]=CategoryDropDown.SelectedItem.Value;
}
else
state["ConstrainCategory"]="false";
if (SupplierCheckBox.Checked){
state["ConstrainSupplier"]="true";
state["SupplierID"]=SupplierDropDown.SelectedItem.Value;
}
else
state["ConstrainSupplier"]="false";
return state;
}
</script>
Demonstrations > Client state |