Thursday, February 26, 2009

Referencing a web control inside a formview from client-side javascript

A quick tip. If you need to reference a web control in a client-side javascript, you would normally do something like this:

<script type="text/javascript" language="javascript">
    function setupMyCheckBox()
        {
            var chkMyCheckBox = document.getElementById('<%=chkMyCheckBox.ClientID%>');
            //...do something with the object here
...


But if the field is inside a formview for example, this is how you would reference it:

<script type="text/javascript" language="javascript">
    function setupMyCheckBox()
        {
            var chkMyCheckBox = document.getElementById('<%=frvMyForm.FindControl("chkMyCheckBox").ClientID%>');
            //...do something with the object here
...

One thing to keep in mind. If you have different formview or gridview modes. (such as view, edit and insert). Then you must setup a "dummy hidden control" in each mode's section in order to avoid an object not found error in the javascript code. You can set it to be a literal or if you are referencing it in code-behind, set it to be the same type as the original field but hidden. Here is an example when setting it as a literal. Note this field has no use except to avoid an error when running the FindControl method in the javascript.

<asp:Literal ID="chkMyCheckBox" runat="server" Visible="false">asp:Literal>

Thursday, February 19, 2009

Joining two DataTables

Lets say you just brought back some data from a query and you want to rearrange the data or you simply have two datatables with the same schema that you want to join. Here is some sample code that will place the main customer first and then the additional customers sorted by customerId:


// Customers Object
clsCustomers objCustomers = new clsCustomers();

// Get Main Customer ID and Customer DataSet
int customerId = objCustomers.getMainCustomer();
DataSet dsCustomers = objCustomers.getCustomers();

// Create Temp Table to hold Main/Additional Customers sorted with Main Customer First
DataTable dtTempTable = new DataTable();

// Create Temp View to hold Main/Additional Customers
DataView dvCustomer;

// Setup Main Customer using RowFilter
dvCustomer = dsCustomers.Tables["Default"].DefaultView;
dvCustomer.RowFilter = "customerId = '" + customerId + "'";

// Add Main Customer to Temp Table
// The ToTable method is used to copy just the results of the RowFilter
dtTempTable = dvCustomer.ToTable();

// Setup Additional Customers using RowFilter and Sorting
dvCustomer = dsCustomers.Tables["Default"].DefaultView;
dvCustomer.RowFilter = "customerId <> '" + customerId + "'";
dvCustomer.Sort = "customerId";

// Add Additional Customers to Temp Table
// The Merge method is used to merge the two tables together
dtTempTable.Merge(dvCustomer.ToTable(), false, MissingSchemaAction.Add);

All Done! Now you have your DataTable dtTempTable sorted with the main customer first and then the rest of the customers sorted by customerId.

Wednesday, February 4, 2009

FormView, User Controls and Events

Lets say you have a webform (aspx) with a formview that has a user control inside. How would you handle an event from the user control in your webform?

Since the user control is inside the formview, you cannot just place the code in the OnInit method like you might do for events that are part of your web form:

        protected override void OnInit(EventArgs e)
        {
 
            // First call the base oninit
            base.OnInit(e);
 
            // Add Event Handler for new request created - This will not work:
            usrMyControl1.CustomerCreated += new EventHandler(CustomerCreated);
        }


The reason being that the control has not been created yet. It will be created later on when you bind your FormView. So, the correct place to create the handler is in the ItemCreated method of the FormView :

        protected void frvCustomers_ItemCreated(object sender, EventArgs e)
        {
            // When handling an event of a user control inside a formview, you must add 
            // the event handling inside the ItemCreated method
            usrMyControl usrMyControl1 = (usrMyControl)frvCustomers.FindControl("usrMyControl1");
            usrMyControl1.CustomerCreated += new EventHandler(CustomerCreated);
        }

We now know the proper place to create the handler. But, you might not need to create a handler. If you only want to handle lets say an ok button pressed on the user control, you can simply use the fact that on a postback the PreRender method is called and no need to create or handle the above event!

        protected void frvCustomers_PreRender(object sender, EventArgs e)
        {
 
            try
            {


// Here you can create an instance of the user control
// then you can get its properties and use those properties
// in your webform for example to change the value of a textbox

                // Reference the objects from the FormView
                TextBox txtFirstName = (TextBox)frvCustomers.FindControl("txtFirstName");
 
 
                // Access User Control if the ok button was pressed (objCustomerPicker object exists)
                usrMyControl usrMyControl1 = (usrMyControl)frvCustomers.FindControl("usrMyControl1");
                if (usrMyControl1.objCustomerPicker != null)
                {
// Set FormView data from user control
                    clsCustomerPicker objCustomerPicker = usrMyControl1.objCustomerPicker;
                    txtFirstName.Text = objCustomerPicker.firstName;
                }
 
            }
 
            catch (Exception ex)
            {
                lblStatus.Text = "ERROR: frvCustomers_PreRender: " + ex.Message;
            }
 
        }


The clsCustomerPicker class is just a Serializable class that contains the properties of the user control:

[Serializable()]
    public class clsCustomerPicker 
    {
 
        // Public Variables 
        public string country;
        public string firstName;
        public string lastName;
        public string cellphone;
 
    } 


Basically following the above example of clicking on a button. You would have a method in your user control that handles the ok button, instantiates the above class and sets the values of the class such as country, firstname, etc. I also save the values to viewstate after to access them from the web form during pre_render of the formview:

                // Save Object in viewstate, you would place this in the function
// handling the submit of the button inside the user control
                ViewState["objCustomerPicker "] = objCustomerPicker;


Finally you set up the method to get the values of the class in viewstate:

        public clsCustomerPicker objCustomerPicker 
        {
            get
            {
                // Send Back Value
                if (ViewState["objCustomerPicker"] != null)
                    return (clsCustomerPicker )ViewState[" objCustomerPicker"];
                else
                    return null;
            }
        }



And thats all. You now have seen a couple of options on how to handle data inside a formview which uses a user control.