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
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:
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
Gracias "Elektro" pero me salen estos dos errores en tú código, mira: El primero es con la propiedad "FirstOrDefault"
(http://i1065.photobucket.com/albums/u400/lordbynary/Error1_zps4be5897b.png)
Y luego este también: El segundo es con la propiedad "methodParams.ToArray"
(http://i1065.photobucket.com/albums/u400/lordbynary/Error2_zpsf801bf5b.png)
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