Cómo Cambiar las Propiedades de un Control con "Reflection" ???

Iniciado por LordBynary, 20 Enero 2015, 16:29 PM

0 Miembros y 1 Visitante están viendo este tema.

LordBynary

Hola a todos, he estado viendo el tema de "CodeDom" y "Reflection" en este link: http://www.codeproject.com/Articles/12852/Compile-and-Run-VB-NET-Code-using-the-CodeDom y tengo un pequeño problema con eso.

Bueno el tema es que quisiera saber: Cómo Puedo Cambiar las Propiedades de un Control con "Reflection" en Tiempo de Ejecución, les explico mejor mi duda y les planteo el escenario:

1.- Tengo un "Formulario" llamado "Form1".
2.- Tengo 2 "Textbox", llamados: "TextBox1" y "TextBox2" Respectivamente.
3.- También tengo un "Button" llamado "Button1".

Ahora lo que quiero hacer es lo siguiente:

- Que al ingresar en el "TextBox1" el texto "TextBox2.Enabled = False", y presionar el "Button1", se deshabilite automáticamente el TextBox2 en Tiempo de Ejecución.

Por Favor les pido que me ayuden, es urgente el tema.

Gracias a todos de antemano.




Elektro quisiera que me ayudes ahora sí aquí, o a los moderadores de este foro les pido que me ayuden con esto, o a cualquier persona que sepa algo sobre esto.




[MOD]: Está prohibido hacer doble post, utiliza el botón "Modificar" :P

Eleкtro

#1
En el caso específico del problema que has expuesto, puedes hacerlo por ejemplo así:

Ten en cuenta que el siguiente código no está pulido, es solo un ejemplo, y se podría simplificar o parsear el string de otra manera más eficiente.

EDITO: Versión extendida:

Código (vbnet) [Seleccionar]
Imports System.Reflection
Imports System.Globalization

Public Class Form1

   Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
   Handles Button1.Click

       Me.ParseControlInstruction("Textbox2.Enabled = False")
       Me.ParseControlInstruction("Textbox2.Hide()")

   End Sub

   Private Sub ParseControlInstruction(ByVal instruction As String)

       Dim isProperty As Boolean
       Dim isMethod As Boolean

       If instruction Like "*[.]*[!(]*[=]*" Then
           isProperty = True

       ElseIf instruction Like "*[.]*[!=]*[(]*[)]" Then
           isMethod = True

       Else
           Throw New NotImplementedException(String.Format("Cannot recognize the instruction string: {0}", instruction))

       End If

       ' Fix whitespaces.
       instruction = instruction.Trim({" "c})

       ' Fix Namespaces. (THIS IS NOT PROPERLY IMPLEMENTED)
       If instruction.StartsWith("Me.", StringComparison.OrdinalIgnoreCase) Then
           instruction = instruction.Remove(0, "Me.".Length)
       End If

       Dim ctrlName As String = instruction.Substring(0, instruction.IndexOf("."c))

       If isProperty Then
           Dim propName As String = instruction.Remove(0, ctrlName.Length + 1)
           propName = propName.Substring(0, propName.IndexOf(" "c))

           Dim value As Object = instruction.Substring(instruction.IndexOf("="c) + 1).Trim({" "c})

           Me.SetControlProperty(ctrlName, propName, value, MyBase.Controls, searchChildrens:=True)

       ElseIf isMethod Then
           Dim methodName As String = instruction.Remove(0, ctrlName.Length + 1).TrimEnd({"("c, ")"c})

           Dim methodParamsStr As String = instruction.Substring(instruction.IndexOf("("c) + 1)
           methodParamsStr = methodParamsStr.Substring(0, methodParamsStr.LastIndexOf(")"c))
           Dim methodParams As IEnumerable(Of Object) = methodParamsStr.Split({", "}, StringSplitOptions.RemoveEmptyEntries)

           Me.CallControlMethod(ctrlName, methodName, methodParams, MyBase.Controls, searchChildrens:=True)

       End If

   End Sub

   Private Sub SetControlProperty(ByVal ctrlName As String,
                                  ByVal propName As String,
                                  ByVal value As Object,
                                  ByVal controlCollection As Control.ControlCollection,
                                  Optional ByVal searchChildrens As Boolean = False,
                                  Optional ByVal searchFlags As BindingFlags =
                                                                BindingFlags.IgnoreCase Or
                                                                BindingFlags.Instance Or
                                                                BindingFlags.Public Or
                                                                BindingFlags.NonPublic)

       Dim ctrl As Control = controlCollection.Find(ctrlName, searchChildrens).FirstOrDefault
       Dim prop As PropertyInfo

       Select Case ctrl Is Nothing

           Case False
               Try
                   prop = ctrl.GetType().GetProperty(propName, searchFlags)

               Catch ex As AmbiguousMatchException
                   Throw New AmbiguousMatchException(String.Format("More than one property found with the same name: {0}", propName))
                   Exit Sub

               End Try

               Select Case prop Is Nothing

                   Case False
                       Try
                           prop.SetValue(ctrl, Convert.ChangeType(value, prop.PropertyType), Nothing)

                       Catch ex As Exception
                           Throw

                       End Try

                   Case Else
                       Throw New NullReferenceException(String.Format("Property not found by name: {0}", propName))

               End Select ' prop Is Nothing

           Case Else
               Throw New NullReferenceException(String.Format("Control not found by name: {0}", ctrlName))

       End Select ' ctrl Is Nothing

   End Sub

   Private Sub CallControlMethod(ByVal ctrlName As String,
                                 ByVal methodName As String,
                                 ByVal methodParams As IEnumerable(Of Object),
                                 ByVal controlCollection As Control.ControlCollection,
                                 Optional ByVal searchChildrens As Boolean = False,
                                 Optional ByVal searchFlags As BindingFlags =
                                                               BindingFlags.IgnoreCase Or
                                                               BindingFlags.Instance Or
                                                               BindingFlags.Public Or
                                                               BindingFlags.NonPublic)

       Dim ctrl As Control = controlCollection.Find(ctrlName, searchChildrens).FirstOrDefault
       Dim method As MethodInfo

       Select Case ctrl Is Nothing

           Case False
               Try
                   method = ctrl.GetType().GetMethod(methodName, searchFlags)

               Catch ex As AmbiguousMatchException
                   Throw New AmbiguousMatchException(String.Format("More than one method found with the same name: {0}", methodName))
                   Exit Sub

               End Try

               Select Case method Is Nothing

                   Case False
                       Try
                           method.Invoke(ctrl, searchFlags, Nothing, methodParams.ToArray, CultureInfo.InvariantCulture)

                       Catch ex As Exception
                           Throw

                       End Try

                   Case Else
                       Throw New NullReferenceException(String.Format("Method not found by name: {0}", methodName))

               End Select ' prop Is Nothing

           Case Else
               Throw New NullReferenceException(String.Format("Control not found by name: {0}", ctrlName))

       End Select ' ctrl Is Nothing

   End Sub

End Class


Saludos








LordBynary

#2
Gracias "Elektro" pero me salen estos dos errores en tú código, mira: El primero es con la propiedad "FirstOrDefault"



Y luego este también: El segundo es con la propiedad "methodParams.ToArray"


Eleкtro

#3
En las propiedades de tu proyecto, cambia el .Net Framework objetivo del proyecto a .Net framework 3.5 o superior, para añadir la referencia a LINQ.

Saludos