.net - Controles de usuario anidados: la mejor forma de obtener una referencia a un control ancestral
user-controls nested (5)
Me doy cuenta de que aquí no caben muchos códigos, pero estoy pidiendo una dirección general o un puntero.
Tengo controles de usuario .NET anidados seis profundidades para un gadget interactivo con (externo a interno) de: envoltorio, pestañas, paneles, listas, filas, elementos.
Estoy tratando de obtener una referencia a un control ancestral desde un control anidado.
Específicamente, tengo este código en el código detrás de un control incrustado de "gran bisnieto". Funciona, pero es muy feo
MyTab _myTab = this.Parent.Parent.Parent.Parent.FindControl(thisTab) as MyTab;
que es igual a {ASP.controls_appname_widget_mywidget_mytab_ascx}
y es correcto.
Me doy cuenta de que puedo hacer algo como Page.FindControl ("MyWrapper: MyPanel: etc .....) pero eso tampoco se recomienda, ya que la estructura o los ID pueden cambiar ...
¿Hay una alternativa decente?
@Andrew, no para secuestrar mi propio hilo sino solo para aclarar y discutir un enfoque de diseño. Usted ha dicho "nunca quiere tener ningún control para tener conocimiento de algo superior a sí mismo en la jerarquía ...". Esa es una estrategia de gran diseño por razones obvias. Pero, ¿qué pasa con el caso de un contenedor contenedor con algún tipo de gestión centralizada integrada? Por ejemplo, en .NET, un control ScriptManager en una página maestra anidada. Querrá que se cree un administrador de scripts una sola vez, y le gustaría que esté disponible para varios controles en la aplicación. Por ejemplo, cualquier UpdatePanel en cualquier control incrustado en la aplicación querría saber sobre la existencia de ese ScriptManager. ¿Es este un enfoque equivocado?
Mi diseño es similar: el contenedor externo más externo administra la persistencia del objeto, y cada control puede guardar su estado en ese Administrador. Estoy pensando ahora que los delegados de envoltura son el mejor diseño para esto. Porque no me gusta el Parent.Parent. etc. ni atravesando los ID de control solo para hacer una referencia. Cualquier comentario bienvenido.
Creo que realmente depende de tu uso de los controles. Si el control solo satisface una necesidad comercial y solo se utiliza en una página para satisfacer un caso de uso, entonces no hay necesidad de volverse loco con las interfaces y las propiedades. No veo nada malo con la idea de parent.parent.parent.etc; lo usé muchas veces yo mismo. Sin embargo, lo envolvería en una propiedad para que siempre que lo necesite pueda llamar a este. Mi Gran Propaganda. Será más legible y si la profundidad de su jerarquía cambia, solo tiene un lugar para arreglar.
Ahora bien, si se trata de un componente genérico que no controla el uso de, o será necesario en muchos casos de uso, deberá agregar propiedades para que el padre le diga quiénes son para mantener el desacoplamiento.
Hola, podrías usar el selector WebControl, que en realidad es un proyecto independiente (licencia == LGPL) pero aún forma parte de la descarga principal de Ra-Ajax ...
Consulte el código y el uso de muestra aquí ...
Luego, puede buscar desde el objeto de la página y buscará de forma recursiva un control que coincida con sus criterios (cualquiera que sea) en el delegado ...
Recuerde que los componentes se ignoran mejor. Nunca desea que ningún control tenga ningún conocimiento de algo superior a él en la jerarquía y que tenga conocimiento de controles solo de interfaz sobre sí mismo en la jerarquía. Este enfoque arquitectónico le ahorrará mucho dolor y sufrimiento a largo plazo y evitará situaciones como las que tiene ahora.
En cuanto a la solución del problema actual, la mejor manera de solucionarlo es crear un miembro MyTab
en su control que sea configurable por los controles principales. Esta no es una solución perfecta ya que su control no es totalmente ignorante de los demás, pero al menos ya no tendrá que saber cómo obtener la referencia de MyTab
, se le proporcionará.
Así que crearía una propiedad llamada algo así como ParentTab
y establecería esta propiedad igual a la referencia de MyTab
en algún lugar de la página o dentro de un control que tenga y tenga visibilidad tanto para MyTab
como para su control.
public static class Extension{
public static Control FindControlRecursive(this Control control, string idToFind)
{
Control result;
if(control != null){
result = control.FindControl(idToFind);
}
if(result != null){ return result; }
if(result == null && control.Parent != null){
return control.Parent.FindRecursive(idToFind);
}
return null;
}
}