interactive | editorial | code | resource 
Demonstrations > Interaction
 

Interaction

This page shows how two DbCombo controls can interact with each other. In this example the products DbCombo will only contain products specific to the selected supplier. If no supplier is chosen, all products will be displayed.

Select supplier:     
Select product:     

The code:

The code for this page follows:

First we define our page, and import some namespaces we will be using. Note that we have specified AutoEventWireup="true". This is important as we will be using the Page_Load function.

<%@ Page 
    Language="c#" 
    AutoEventWireup="true" %>
    
<%@ Register 
    TagPrefix="DbCombo" 
    Namespace="Cambro.Web.DbCombo" 
    Assembly="Cambro.Web.DbCombo" %>
    
<%@ Import Namespace="Cambro.Web.DbCombo" %>
<%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

This is the start of the page code (something like this is inserted by Visual Studio).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
<html>
<head><title>DemoInteraction</title></head>
<body MS_POSITIONING="GridLayout" XMLNS:DbCombo="http://schemas.cambro.net/dbcombo">
<form id="DemoInteraction" method="post" runat="server">

Here are our two DbCombo controls. The Supplier DbCombo will have its value tracked by the SupplierOnSelect function. This function will simply read out the SupplierID each time it is changed, and store it in a JavaScript variable.

<p>
    <table>
        <tr>
            <td>
                Select supplier:
            </td>
            <td>
                <DbCombo:DbCombo 
                    runat="server" 
                    ID="SupplierCombo" 
                    ServerMethod=SupplierServerMethod
                    CloseResultsOnBlur="false" 
                    ClientOnSelectFunction="SupplierOnSelect" />
            </td>
            <td>
                Select product:
            </td>
            <td>
                <DbCombo:DbCombo 
                    runat="server" 
                    ID="ProductCombo" 
                    ServerMethod=ProductServerMethod
                    CloseResultsOnBlur="false" 
                    ClientStateFunction="ProductState()" 
                    OnGetDownLevelState="DownLevelProductState" />
            </td>
        </tr>
    </table>
</p>

Now the JavaScript:

First we define a variable that will be used to store the value of the SupplierID.

<script language=javascript>

    var SupplierID=-1;

Next the SupplierOnSelect function. This simply the Value property from the DbCombo, and stores it in the JavaScript variable we have just defined. If the event observed is a clear event, -1 is stored. Note that each time we change the value, we call the UpdateProduct() JavaScript function. This tells the Product DbCombo that its page state has changed.

    function SupplierOnSelect(Value, Text, SelectionType)
    {
        switch (SelectionType)
        {
            case 1: // The user is scrolling down the list 
                    // ClinetOnSelectFunction fires each 
                    // time a new item is selected.
            case 3: // The user has clicked on an item. The 
                    // results disappear, and the item is 
                    // selected.
            case 8: // The user has entered an exact match to 
                    // one of the data items. This item is 
                    // selected.
            case 9: // In a ‘re-query on postback’ or an 
                    // ‘auto-query on load’, both the text and 
                    // value properties have matched with one 
                    // of the items. This item is selected.
                if (SupplierID != Value)
                {
                    SupplierID = Value;
                    UpdateProduct();
                }
                break;
            case 2: // The user has pressed enter when an item 
                    // is selected. The results disappear, and 
                    // the item is selected.
                break;
            case 4: // The user has entered more text into the 
                    // textbox. Another query will be run, and 
                    // the selection is cleared. Nothing is 
                    // selected.
            case 5: // The user has scrolled off the bottom or 
                    // top of the drop-down, and cleared the 
                    // current selection. Nothing is selected.
            case 6: // The user has pressed escape to clear 
                    // the DbCombo, and hide the results. 
                    // Nothing is selected.
            case 7: // DbCombo has evaluated the client state 
                    // function, and found it to have changed. 
                    // The current selection is cleared. 
                    // Nothing is selected.
                if (SupplierID != -1)
                {
                    SupplierID = -1;
                    UpdateProduct();
                }
                break;
            default:
                break;
        }
    }

Next the ProductState function. This simply uses the JavaScript variable we defined earlier to store the state of the page.

    function ProductState()
    {
        var state = new Object();
        state["SupplierID"]=SupplierID;
        return state;
    }

Lastly we define our UpdateProduct JavaScript function. This executes the DbComboStateChanged JavaScript function with the UniqueID of the Product DbCombo as its parameter. This DbComboStateChanged function is contained in DbCombo's JavaScript support file. Note that we initially check that DbCombo's JavaScript support file exists - it will not exist in DownLevel browser mode.

    function UpdateProduct()
    {
        if (typeof(DbComboServerExists)!='undefined')
        // This checks to make sure the DbCombo javascript 
        // file exists - if we are in down-level mode, the 
        // next line would fail.
            DbComboStateChanged('<%# ProductCombo.UniqueID %>');
            // This informs a specific DbCombo that it's 
            // ClientState has changed. It will reevaluate 
            // it, and if it has changed, it will get new 
            // data from the server.
    }
    
</script>

Next we start on the server code:

The Page_Load function simply contains Page.DataBind(). Without this the <%# ProductCombo.UniqueID %> block above will not be rendered to the page.

<script runat="server">

    private void Page_Load(object sender, System.EventArgs e)
    {
        // We have to have this line or the <%# ... %>
        // blocks won't be bound.
        Page.DataBind();
    }

Our first ServerMethod provides data for the Supplier DbCombo. It's a completely standard ServerMethod.

    [Cambro.Web.DbCombo.ResultsMethod(true)]
    public static object SupplierServerMethod(
        Cambro.Web.DbCombo.ServerMethodArgs args)
    {

        // We create a dataset and open the data connection
        DataSet dataset=new DataSet();
        SqlConnection conn = new SqlConnection("[YOUR-CONNECTION]");
        SqlDataAdapter adapter = new SqlDataAdapter();
        
        // We construct our query and add a parameter
        adapter.SelectCommand = new SqlCommand(@"
                    SELECT TOP "+args.Top+@" 
                        CompanyName AS DbComboText, 
                        Suppliers.SupplierID AS DbComboValue 
                    FROM Suppliers 
                    WHERE CompanyName LIKE @Query 
                    ORDER BY CompanyName", conn);
        adapter.SelectCommand.Parameters.Add("@Query", args.Query+"%");
        
        // We fill the dataset and return it.
        adapter.Fill(dataset);
        conn.Close();
        return dataset;
                
    }

Our second ServerMethod provides data for the Product DbCombo. It uses the contents of the ClientState Hashtable to create an additional WHERE clause, which it appends to the SQL query.

    [Cambro.Web.DbCombo.ResultsMethod(true)]
    public static object ProductServerMethod(
        Cambro.Web.DbCombo.ServerMethodArgs args)
    {

        // We construct a string that may contain an additional 
        // WHERE clause for our SQL query.
        string extraWhereClause = "";
        if (args.ClientState!=null)
        {
            if (
                args.ClientState["SupplierID"] != null && 
                args.ClientState["SupplierID"].ToString()!="-1" 
                )
            {
                extraWhereClause += " AND SupplierID = " + 
                    int.Parse(args.ClientState["SupplierID"].ToString())
                    + " ";
            }
        }

        // We create a dataset and open the data connection
        DataSet dataset=new DataSet();
        SqlConnection conn = new SqlConnection("[YOUR-CONNECTION]");
        SqlDataAdapter adapter = new SqlDataAdapter();
        
        // We construct our query and add a parameter. We also add 
        // the additional WHERE clause that we created earlier. Note 
        // that the string may be empty.
        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+"%");
        
        // We fill the dataset and return it.
        adapter.Fill(dataset);
        conn.Close();
        return dataset;
                
    }

This last server function provides client-state compatibility with down-level browsers. It emulates the JavaScript ProductState() function, except the values are derived on postback. This function can be removed if your users are all IE5+.

    protected Hashtable DownLevelProductState(DbCombo sender)
    {
        // This function is only used in down-level browser mode. 
        // It returns the same result as the ClientState javascript 
        // function. If you know all browsers will be IE5+, this 
        // function may be omitted.
        Hashtable state = new Hashtable();
        if (SupplierCombo.Value!=null && SupplierCombo.Value!="")
            state["SupplierID"]=SupplierCombo.Value;
        else
            state["SupplierID"]="-1";
        return state;
    }
    
</script>

This is the end of the page code (this is inserted by Visual Studio).

</form>
</body>
</html>

 
Demonstrations > Interaction