Buenas a todos!
Resulta que de vez en cuando, la luna y marte se alinean y nosotros los programadores tenemos que arremangarnos para resolver los líos en que nos metemos….
Uno de estos líos inocentes puede ser que “alguien” te pase un string que contiene el nombre de un control que tienes en tu formulario y te dice: “haz visible ese control que te pase….. ahh se me olvidaba, el control puede estar metido dentro de tabpanels, panels o group panels…. por lo que eso de Form.Controls(“nombredelcontrol”) no va….” -_-!
Como si fuese tan facil…. pues sip, si que lo es, 2 linea de codigo, gracias a nuestro siempre querido reflection!!!
Dim obj As Object
obj = Owner.GetType().GetField(“_” & name,Reflection.BindingFlags.NonPublic Or _
Reflection.BindingFlags.Instance Or _
Reflection.BindingFlags.IgnoreCase).GetValue(Owner)
El primer parámetro de la función GetField es el nombre de control, se le pasa “_” porque el nombre en el ensamblado está precedido de “_”, sin este no encontrará el control.!
Con esto obj contendra nuestro objeto y podremos modificar, eliminar o cambiar todo lo que queramos, quedando reflejado en nuestro objeto real. Solo con algunas lineas más de código dejaremos nuestro código mucho más reusable….
Public Function EncontrarControl(ByVal name As String, ByVal Owner As Form) As Control
Dim obj As Object
Try
obj = Owner.GetType().GetField(“_” & name,Reflection.BindingFlags.NonPublic Or _
Reflection.BindingFlags.Instance Or _
Reflection.BindingFlags.IgnoreCase).GetValue(Owner)
Owner.GetType().GetFiel()
Return (CType(obj, Control))
Catch ex As Exception
Return Nothing
End Try
End Function
Y listo! solo con invocar nuestra función podemos acceder directamente a las propiedades de nuestro control y modificarlo y usarlo:
EncontrarControl(“Nombredelcontrol”, Form1).Visible = True
Hasta la próxima.
Happy Coding!
2 marzo 2009 a las 8:48 pm
Compañero no si esto sirve para C# ya que lo implemento pero no me funciona, si me pudieras dar una ayuda.
3 marzo 2009 a las 1:53 pm
Buenas Luis!
Intentaré ayudarte, puedes darme algo más de info? te da algún error, simplemente no hace nada…. o pega el codigo en c# y le hecho un vistazo a ver si te puedo hechar un cable!
3 marzo 2009 a las 2:52 pm
Gracias tenerifedotnet, mi situación es la siguiente:
Estoy implementando un sistema con multilenguaje, entonces en el load de cada formulario instancio una clase que ejecuta unos métodos que me transcriben el lenguaje dependiendo del usuario que este logueado en el sistema, con los sistemas web no tengo ningún problema, sino que estos empiezan cuando la aplicación es windows form y los controles se encuentran dentro de otros controles como paneles. Te muestro como lo hago y se que funciona tanto para web y windows con la exepción que te expliqué:
// Iterates throught the translations of the page
foreach (DataRow vloRow in vlaTranslations)
{
// Searches the control in the page
vloControl = pvoForm.Controls[vloRow["ControlId"].ToString().Trim()];
//vloControl = pvoForm.Controls.Find(vloRow["ControlId"].ToString().Trim(), true);
// If the control was found
if (vloControl != null)
{
// The translation should be performed over a Control Property.
if (vloRow["ControlProperty"] != DBNull.Value)
{
// Translante the control property
TranslateControlProperty(vloRow, vloControl);
}
// The translation should be performed over a Control Collection
else
{
// Translate control collection
TranslateItemOfCollection(vloRow, vloControl);
}
}
// The control was not found
else
{
// Throw an exception
throw new Exception(string.Format(CONTROL_NOT_FOUND, vloRow["ControlId"].ToString().Trim(), vlcPageName));
}
}
El método anterior busca dentro del formulario pasado por parámetro de la siguiente manera
Formulario.Controls[NombreControl] != Null
Quiere decir que el control existe y llamo al método que setea la propiedad Text, pasandole el objeto, la propiedad en formato String y el nuevo valor que debe llevar
public static void SetPropertyValue(object pvoObject, string pvcProperty, object pvcValue)
{
// Para almacenar la lista de propiedades para llegar a la propiedad a actualizar
string[] vlaProperties;
// Para almacenra una propiedad
System.Reflection.PropertyInfo vloProperty;
try
{
// Obtener la lista de propiedades para llegar a la propiedad a modificar
vlaProperties = pvcProperty.Split(new char[] { ‘.’ }, StringSplitOptions.RemoveEmptyEntries);
// Para cada uno de de los nombres de las propiedades anteriores a la final
for (int i = 0; i < vlaProperties.Length – 1; i++)
{
// Obtener la información de la propiedad
vloProperty = pvoObject.GetType().GetProperty(vlaProperties[i]);
// Obtener el objeto que referencia la propiedad
pvoObject = vloProperty.GetValue(pvoObject, null);
}
// Obtener la propiedad a modificar
vloProperty = pvoObject.GetType().GetProperty(vlaProperties[vlaProperties.Length - 1]);
// Modificar el valor de la propiedad
vloProperty.SetValue(pvoObject, pvcValue, null);
}
catch (Exception vloException)
{
// Lanzar una excpeción
throw new Exception(string.Format(PROPERTY_NOT_FOUND, pvcProperty, “”, “”));
}
}
Cuando se presentan controles que estan dentro de un panel:
Formulario.Controls[NombreControl] != Null
Esto siempre me devuelve Null, indicandome que el control no existe. Por lo que lo cambio por :
Formulario.Controls.Find[NombreControl] != Null
Ya con la linea anterior si me encuentra los controles que tengo dentro de otros controles, pero a la hora de llamar al metodo donde envio el objeto, la propiedad y el nuevo valor, me indica que la propiedad no existe. Por lo que estoy llevando a cabo una investigación para dar una solución a mi problema.
Intento utilizar tu método pero me da tres problemas:
public static Control EncontrarControl(String pvcNombreControl, Form pvoFormulario)
{
Object obj;
try
{
obj = pvoFormulario.GetType().GetField(“_” + pvcNombreControl, System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase).GetValue(pvoFormulario);
pvoFormulario.GetType().GetField();
return (Convert.ChangeType(obj, Control));
}
catch (Exception vloException)
{
return null;
}
}
La línea siguiente:
pvoFormulario.GetType().GetField();
Error: Sobre carga de métodos, cero argumentos.
return (Convert.ChangeType(obj, Control));
Error: Control es un tipo y esta siendo usado como variable
por lo que lo intento utilizar de la siguiente manera:
public static Object EncontrarControl(String pvcNombreControl, Form pvoFormulario)
{
Object obj;
try
{
obj = pvoFormulario.GetType().GetField(“_” + pvcNombreControl, System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase).GetValue(pvoFormulario);
return obj;
}
catch (Exception vloException)
{
return null;
}
}
Pero la línea siguiente:
obj = pvoFormulario.GetType().GetField(“_” + pvcNombreControl, System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase).GetValue(pvoFormulario);
Me dispara el siguiente error:
Object reference not set to an instance of an object
Por lo que no puedo ejecutar el método.
Espero que con esto puedas entender y me puedas brindar algún tipo de ayuda, gracias de antemano.
3 marzo 2009 a las 3:57 pm
tenerifedotnet te comunico que investigando un travesiando un poco más encontre la solución a mi problema con la ayuda de tu método, te muestro la implementación y muchas gracias.
public static Control EncontrarControl(String pvcNombreControl, Form pvoFormulario)
{
Object obj;
try
{
System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance;
Type t = pvoFormulario.GetType();
System.Reflection.FieldInfo fi = t.GetField(pvcNombreControl, flags);
return ((Control)fi.GetValue(pvoFormulario));
}
catch (Exception vloException)
{
return null;
}
}
3 marzo 2009 a las 5:37 pm
Buenas tardes Luis!
Me alegra mucho que encontrases la solución al problema, y me alegra haberte ayudado un poco! gracias por visitarnos, espero poder volver a publicar algun articulo en breve.
Un saludo muy grande!!!