Una de las Best Practices de todos los proyectos es tener tu propia coleccion de Custom Controls aunque a priori no vayamos a necesitarla. Basta con que heredemos de los controles del framework y cuando necesitemos implementar algo en todo nuestro proyecto veremos recompensada esta accion.
En mi proyecto tenemos todos los controles de la UI customizados y hemos ido añadiendo funcionalidad poco a poco, pero el otro dia me encontre un problema que os detallo a continuacion, asi como la solucion que elegimos para arreglarlo.
Muchas veces cuando creamos un control que va a usarse en todo nuestro proyecto no pensamos en todas posibles situaciones en las que este va a ser usado. Es imposible. Por motivos funcionales nos vimos obligados a añadir una serie de atributos a todos los controles, para diseñar un mecanismo que detectara en cliente si se habia modificado algun valor y poder preguntar asi al usuario si queria guardar los cambios antes de proceder a la navegacion hacia otra pagina de la aplicacion.
Pues nos pusimos manos a la obra. En nuestro CustomTextBox añadimos en el PreRender un atributo "onchange" que cambiaba el valos de un HiddenField marcando la pagina como "modificada".
Un mes mas tarde alguien necesitaba añadir cierta logica cliente para que, en un textbox determinado, al cambiar de valor, realizara una comprobacion de si este nuevo valor cumplia con una serie de restricciones. La persona encargada de esto hizo lo que tenia que hacer, añadio un atributo "onchange" a su textbox y la llamada a la funcion javascript que se habia creado, pero no le funcionaba. Despues de varias horas pensando que el problema era suyo, vino a hablar conmigo y vimos que su codigo era perfecto, el problema venia de mas arriba.
Al añadir en el PreRender del CustomTextBox el atributo "onchange" para el mecanismo de deteccion de cambios estabamos machacando cualquier otro atributo "onchange" que alguien, desde cualquier pagina de la aplicacion, quisiera añadir.
La solucion.
Despues de pensar en cual seria la mejor solucion para evitar esto hicimos lo siguiente. Antes de añadir cualquier atributo en cualquiera de nuestros Custom Controls decidimos chequear si ese atributo ya existia, y en ese caso, si el valor del atributo no era el mismo que queriamos añadir, lo concatenabamos para que se llamara a ambos.
Despues de ver que esto funcionaba perfectamente hicimos un pequeño refactoring para que quedara mas bonito y no tener codigo duplicado, creando un metodo del tipo AddAttributeSafety(string attibuteType, string attributeValue) que hacia todo lo que explicaba antes.
Solo una ultima cosa. Siempre que añadais un atributo para hacer cosas en cliente a un control, aseguraros de que terminais el codigo del valor del atributo con ";", porque si no no podreis concatenar mas de una accion sobre el mismo evento.
Este es el codigo del metodo para añadir atributos de forma segura en Custom Controls:
private void AddAttributeSafety(string attributeType, string attributeValue)
{
if (attributeType.Length == 0 attributeValue.Length == 0)
{
return;
}
if (Attributes[attributeType] == null Attributes[attributeType].Length == 0)
{
Attributes.Add(attributeType, attributeValue);
}
else
{
string existingAttribute = Attributes[attributeType];
if (existingAttribute.IndexOf(attributeValue) == -1)
{
Attributes.Add(attributeType, existingAttribute + attributeValue);
}
}
}Como siempre espero que le sea util a alguien, y si se os curre algo mejor, compartirlo :D