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.

2 comments:

  1. hi adiel

    How do you reference the usercontrol type (usrMyControl in your example) to make an instance of that type?

    ReplyDelete
  2. Alvaro, thanks for you comment. If I understand you question correctly, you should be able to reference the user control if it is in the same namespace without doing anything. However, your user control could be in a different namespace and if that is the case, you can add a reference to the namespace. For example, bring up the code behind for your user control and look at the line:

    namespace MyApp.userControls

    In the above example, the namespace is MyApp.userControls. If this namespace is different from the namespace where you are referencing the user control type, add this to the top of the form where you will be adding a reference to the user control:

    using MyApp.userControls;

    You will now be able to reference your usercontrol type.

    Thanks,
    Adiel

    ReplyDelete