domingo, 5 de junio de 2011

(Repeater - Checkbox - CommandName) ItemCommand en repeaters por parte de Checkboxes

En esta ocasión les traigo una solución a un problema con el que me encontré varias veces. Si alguna vez tuvieron que usar checkboxes que disparen el evento OnItemCommand en un repeater, se habrán dado cuenta de que, no importa lo que hagan, el evento NO se dispara. Esto es por la forma en la que el radiobutton esta implementado (por alguna razón que desconozco, MS decidió de que, estos componentes usados dentro de un repeater no iban a comportarse como los linkbuttons o los buttons que todos queremos y estamos acostumbrados a usar).
Navegando un poco me encontré con este articulo, que me permitio hechar un poco de luz al respecto (el código de ejempo SI esta en C#).
Mientras que el botón y el linkbutton, cuentan con un metodo "OnCommand", y una llamada a dicho método, dentro de su "RaisePostbackEvent" (con el CommandName y el CommandArgument como parametros), por alguna razon, el checkbox NO lo posee.
Dicho Método ("OnCommand"), llama a "RaiseBubbleEvent", el que permite proyectar los parámetros (CommandName y CommandArgument) a quien sea que este escuchando (en este caso nuestro repeater, que implementa el "OnBubbleEvent"). Como nuestros checkboxes NO implementan este "OnCommand", nunca se dispara el "RaiseBubbleEvent", con los CommandName y CommandArgument y nunca se llega al "OnBubbleEvent" del repeater.

Como solución a esto encontré una implementación "custom" de un checkbox que sobre escribe el "OnCheckedChanged" invocando al metodo "RaiseBubbleEvent" que necesitamos pasándole los valores que queremos (CommandName y CommandArgument):


<ToolboxData("<{0}:RadioButtonRepeaterAware runat=server></{0}:RadioButtonRepeaterAware>")> _
Public Class RadioButtonRepeaterAware
Inherits RadioButton

Public Property CommandName As String
Get
If (Me.ViewState("CommandName") Is Nothing) Then
Return String.Empty
Else
Return Me.ViewState("CommandName").ToString
End If
End Get
Set(ByVal value As String)
Me.ViewState("CommandName") = value
End Set
End Property

Public Property CommandArgument As String
Get
If (Me.ViewState("CommandArgument") Is Nothing) Then
Return String.Empty
Else
Return Me.ViewState("CommandArgument").ToString
End If
End Get
Set(ByVal value As String)
Me.ViewState("CommandArgument") = value
End Set
End Property

Protected Overrides Sub OnCheckedChanged(ByVal e As System.EventArgs)
'create a new event args of type command event args
Dim ce = New CommandEventArgs(Me.CommandName, Me.CommandArgument)

'allow the base checkbox to handle the event as normal
MyBase.OnCheckedChanged(e)

'raise the contorls method RaiseBubbleEvent
MyBase.RaiseBubbleEvent(Me, ce)
End Sub
End Class


El codigo esta en VB.net como para complementar el del ejemplo que esta en C#.
Para poder usar este control en el markup de su aspx o ascx, simplemente tienen que registrar el assembly en el cual colocaron dicha clase:

<%@ Register Assembly="MyAssembly" Namespace="MyNamespace" TagPrefix="cc1" %>



<cc1:RadioButtonRepeaterAware ID="chkSelected" AutoPostBack="true" CommandName="Select"
CommandArgument='<%# DataBinder.Eval(Container.DataItem,"CommandArgumentElementHere") %>' runat="server"
>
</cc1:RadioButtonRepeaterAware>



Espero les haya servido.
P.D.: No lo probe, pero intuyo que esto también deberia poder aplicarse para los radiobuttons.

Happy Programming.