FindControl retorna null/nothing en una Content Page
Hoy me he encontrado esta cuestión en las NewsGroup de ASP.NET:
Tengo un control de usuario MiControl1.ascx con un boton con este código:
TextBox oTxt1 = (TextBox)this.Page.FindControl("TextBox1");
Asimismo hay 2 ASPXs:
Pagina1.aspx que contiene el TextBox1 pero no tiene definida una MasterPage.
Pagina2.aspx que contiene el TextBox1 pero ahora si tiene definida una
MasterPage.
Pagina1.aspx y Pagina2.aspx tienen MiControl1.ascx.
Cuando Pagina1.aspx funciona OK. Pero cuando hago lo mismo en la
Pagina2.aspx, FindControl() falla.
Dónde está el problema y cómo lo soluciono?
La verdad es que es una pregunta frecuente que suelo encontrarme y la solución está en la MSDN:
FindControl searches the current naming container for the specified server control.
Un naming container es cualquier control que implementa la interfaz INamingContainer. MasterPage y Content Controls implementan esta interfaz y por tanto son contenedores. La clave está en buscar el control en el contenedor adecuado, por tanto el método FindControl que se usa en el control de usuario busca sólo en el contenedor actual (La página) y como no utiliza recursividad para buscar el control entre toda la jerarquía de controles devuelve null o nothing.
La solución:
TextBox t;
if (Page.Master != null)
{ foreach (Control control in Page.Master.Controls)
{ if (control is HtmlForm)
{ foreach (Control controlform in control.Controls)
{ if (controlform is ContentPlaceHolder)
{ t = (TextBox)controlform.FindControl("TextBox1"); if (t != null)
break;
}
}
}
}
}
else
{ t = (TextBox)Page.FindControl("TextBox1");}
Si la página tiene MasterPage, buscamos en la colección de controles de la MasterPage el control Htmlform que contiene los ContentPlaceHolder y en ellos buscamos el TextBox1, sino directamente buscamos el control en la página.
Como véis la clave está en buscar el control en el contenedor correcto.
Salu2