Obtener el control que realiza un Postback

- 3 minute read

Al realizar una instrumentación de una aplicación es importante saber que acciones ha realizado el usuario en un determinado momento. Una de estas acciones es saber que botón o control se ha pulsado, es decir que control es el que provoca el postback, y naturalmente tenemos que obtenerlo modificando el menor código posible, por ejemplo, modificando el método Page_Load de una clase base de la que hereden todas las páginas de la aplicación.

Creía que con consultar la propiedad «_EVENTTARGET» tendría suficiente, pero mi sorpresa ha venido porque los botones no informan esta propiedad, y de hecho tiene una explicación lógica en la que a estas alturas aún no había caído. Únicamente tenemos esta propiedad en los controles que, para realizar el postback, llaman a la función «__doPostBack», es decir, en todos los controles menos en los _Button y los ImageButton.

Lo primero que se debe hacer en estos casos es buscar, y he tardado 0,27 segundos en encontrar la solución a mi problema en una entrada del año 2006 del blog de Mahesh Singh. Como necesitaba el código en VB.NET me he tomado la libertad de realizar una conversión literal.

La solución se basa en que si tenemos dos botones y pulsamos sobre el segundo sólo este último estará disponible en la colección Page.Request.Form. Así que si queremos saber quien ha provocado el postback y no lo tenemos en el «__EVENTTARGET», podemos suponer correctamente que el que lo ha provocado ha sido un botón (Button o ImageButton), y sólo debemos comprobar que control de la colección Page.Request.Form es un botón y habremos dado con él. Una única condición a tener en cuenta es que los identificadores de los ImageButton terminan con las cadenas «.x» y «.y», que identifican las coordenadas del ratón.

He aquí el código completo del método que comprueba toda la colección de controles del formulario y la llamada desde el Page_Load de la página:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

    If IsPostBack Then
        Response.Write(getPostBackControlName) 
    End If 

End Sub

Private Function getPostBackControlName() As String 
    Dim control As Control = Nothing
    Dim ctrlname As String = Page.Request.Params(__EVENTTARGET)

    If ctrlname IsNot Nothing AndAlso ctrlname <> String.Empty Then
        control = Page.FindControl(ctrlname)
    Else
        ' Si __EVENTTARGET es nulo, el control es de tipo botón y tenemos
        ' que iterar sobre la colección del formulario para encontrarlo
        Dim ctrlStr As String = String.Empty
        Dim c As Control = Nothing
        For Each ctl As String In Page.Request.Form
            If ctl.EndsWith(".x") OrElse ctl.EndsWith(".y") Then
                ctrlStr = ctl.Substring(0, ctl.Length - 2)
                c = Page.FindControl(ctrlStr)
            Else
                c = Page.FindControl(ctl)
            End If
            If TypeOf c Is System.Web.UI.WebControls.Button OrElse _
                TypeOf c Is System.Web.UI.WebControls.ImageButton Then
                control = c
                Exit For
            End If
        Next
    End If
    
    Return control.ID End Function