none
ACCESO PUNTUAL A PROPIEDADES DE UN CONTROL TOOLSTRIPMENUITEM RRS feed

  • Pregunta

  • Tengo en una base de datos vinculado a un usuario el nombre del elemento del menu (como cadena) y 2 campos Boolean Enabled y Visible

    Como puedo establecer puntualmente esas propiedades ya que no me permite conversion del texto en objeto de menu, este codigo funciona correctamente:

      Dim Permiso As BC.dtsUsuarios.PermisosUsuarioRow
      For Each Permiso In clPermisos (variable de una consulta LINQ)

        mnuOperaciones.Enabled = Permiso.Enabled
        mnuOperaciones.Visible = Permiso.Visible

      Next

    La idea es poder hacer algo asi:

      Dim Permiso As BC.dtsUsuarios.PermisosUsuarioRow
      For Each Permiso In clPermisos (variable de una consulta LINQ)

        Dim mnuIndividual As ToolStripMenuItem
        mnuIndividual = CType(Permiso.IdControl.ToString, ToolStripMenuItem)
        mnuIndividual.Enabled = Permiso.Enabled
        mnuIndividual.Visible = Permiso.Visible

      Next

    miércoles, 28 de septiembre de 2011 15:44

Respuestas

  • mmm... como no mencionastes la version del VS que usas te publicare el código...

    la idea seria recorrer el menú hasta encontrar la opción que coincida con el nombre que buscas para que te devuelva la instancia al item del menú para habilitarlo o desabilitarlo.

    ejemplo:

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            ' Enabled/Disable item
            Dim item As ToolStripMenuItem = GetMenuItem("iProductos")
            If item IsNot Nothing Then
                item.Enabled = Not item.Enabled
            End If
    
            item = GetMenuItem("iInventarioActual")
            If item IsNot Nothing Then
                item.Enabled = Not item.Enabled
            End If
    
        End Sub
    
        Private Function GetMenuItem(ByVal name As String) As ToolStripMenuItem
    
            For Each Menu As ToolStripMenuItem In MenuStrip1.Items
                Dim item As ToolStripMenuItem = GetItem(name, Menu.DropDownItems)
                If item IsNot Nothing Then
                    Return item
                End If
            Next
    
            Return Nothing
        End Function
        Private Function GetItem(ByVal name As String, ByVal collection As ToolStripItemCollection) As ToolStripMenuItem
    
            For Each item As ToolStripMenuItem In collection
                If item.Name.Equals(name) Then
                    Return item
                ElseIf item.DropDownItems.Count > 0 Then
                    Dim subItem As ToolStripMenuItem = GetItem(name, item.DropDownItems)
                    If subItem IsNot Nothing Then
                        Return subItem
                    End If
                End If
            Next
    
            Return Nothing
        End Function
    
    


    la función GetMenuItem solo recibe como parametro el nombre del Item del menú a buscar y devuelve un objeto tipo ToolStripMenuItem  y Nothing si no lo encuentra

    la función GetItem() es una función recursiva que busca dentro de cada opción del menú hasta encontrar el item que coincida con el nombre a buscar, recibe como parametro el nombre del item a buscar y la colección ToolStripItemCollection del item del menú donde se esta buscando sin importar la cantidad de sub menús que tenga la opción del menú.

    el ejemplo lo hice en VS2010 si usas esta versión del VS te puedo pasar el projecto de ejemplo.

    ademas sustitute el nombre del menú en la función GetMenu()


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:55
    miércoles, 28 de septiembre de 2011 17:11
  • "FIERIX" preguntó:

    > Como puedo establecer puntualmente esas propiedades ya que no
    > me permite conversion del texto en objeto de menu, este codigo
    > funciona correctamente:
    >
    > La idea es poder hacer algo asi:
    >
    >  Dim Permiso As BC.dtsUsuarios.PermisosUsuarioRow
    >   For Each Permiso In clPermisos (variable de una consulta LINQ)
    >
    >    Dim mnuIndividual As ToolStripMenuItem
    >    mnuIndividual = CType(Permiso.IdControl.ToString, ToolStripMenuItem)
    >    mnuIndividual.Enabled = Permiso.Enabled
    >    mnuIndividual.Visible = Permiso.Visible
    >
    >  Next

    Hola:

    Si he entendido bien el contenido de tu mensaje, deseas referenciar un objeto ToolStripMenuItem existente en un objeto o control MenuStrip, de acuerdo al nombre de usuario que has recuperado de tu base de datos.

    Si es así, como parece ser que estás utilizando consultas LINQ, simplemente te tienes que crear una función (no es necesario, pero queda mejor) que pasándole el nombre del usuario te devuelva su objeto ToolStripMenuItem:

        Private Function GetToolStripMenuItem(ByVal valor As String) As ToolStripMenuItem
    
            Dim query As IEnumerable(Of ToolStripMenuItem) = _
                 From item As ToolStripMenuItem In MenuStrip1.Items.Cast(Of ToolStripMenuItem)() _
                 Where (item.Text.ToLower() = valor.ToLower()) _
                Select item
    
            If (query.ToList.Count > 0) Then
                Return query.ToList(0)
    
            Else
                Return Nothing
    
            End If
    
        End Function
    

    ¿Que no quieres utilizar LINQ? Recorre el clásico bucle For Each de toda la vida:

        Private Function GetToolStripMenuItem(ByVal valor As String) As ToolStripMenuItem
    
            ' Recorremos la colección de elementos del control MenuStrip principal
            ' 
            For Each mnuItem As ToolStripMenuItem In MenuStrip1.Items
    
                ' Comprobamos si el texto especificado se corresponde
                ' con el valor de la propiedad Text del objeto
                ' ToolStripItem actual.
                ' 
                If (mnuItem.Text.ToLower() = valor.ToLower()) Then
                    ' Devolvemos la referencia
                    Return mnuItem
                End If
    
            Next
    
            Return Nothing
    
        End Function
    

    Se comprende que la variable objeto 'MenuStrip1' referencia al objeto MenuStrip principal donde se encuentran los elementos ToolStripMenuItem.

    Cuando desees referenciar el objeto ToolStripMenuItem de un usuario, ejecutarías lo siguiente:

        Dim mnuIndividual As ToolStripMenuItem = GetToolStripMenuItem("Francisco")
    
        If (Not mnuIndividual Is Nothing) Then
            mnuIndividual.Enabled = Permiso.Enabled
            mnuIndividual.Visible = Permiso.Visible
        End If
    

    Espero haber entendido bien tu pregunta. :-)

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.

    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:55
    miércoles, 28 de septiembre de 2011 17:25
  • mira.... otra forma para no recorrer todas las opciones del menú tambien podria ser usando Reflection

    ejemplo:

            Dim field As FieldInfo = Me.GetType().GetField("_iProductos", BindingFlags.Instance Or BindingFlags.NonPublic)
            If field IsNot Nothing Then
                Dim itemMenu As ToolStripMenuItem = CType(field.GetValue(Me), ToolStripMenuItem)
                itemMenu.Enabled = Not itemMenu.Enabled
            End If
    
    


    el unico detalle con VBasic es que le agrega el guion bajo (_) al nombre de la variable, así que hay que agregarsela al string a buscar.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:56
    miércoles, 28 de septiembre de 2011 18:56
  • Marvin, el procedimiento GetItem da una excepcion de conversio cuando se encuentra un separador. Como te parece mejor controlarlo o agregar un condicional hay alguna forma de filtrar solo menuitem antes de aplicar el "For" Se me ocurrio esto, que te parece

     

    Private Function GetItem(ByVal pNombre As String, ByVal collection As ToolStripItemCollection) As ToolStripMenuItem

     

    Dim mnu As ToolStripMenuItem

     

    For Each item As ToolStripItem In collection

     

    If item.GetType Is GetType(ToolStripSeparator) Then

     

    GoTo SIGUIENTE

     

    End If

    mnu = item

     

    If mnu.Name.Equals(pNombre) Then

     

    Return mnu

     

    ElseIf mnu.DropDownItems.Count > 0 Then

     

    Dim subItem As ToolStripMenuItem = GetItem(pNombre, mnu.DropDownItems)

     

    If subItem IsNot Nothing Then

     

    Return subItem

     

    End If

     

    End If

    SIGUIENTE:

     

    Next

     

    Return Nothing

     

    End Function
    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 22:27
    miércoles, 28 de septiembre de 2011 22:26
  • claro, tambien lo podrias resolver asi:

        Private Function GetItem(ByVal name As String, ByVal itemCollection As ToolStripItemCollection) As ToolStripMenuItem
    
            For Each item As ToolStripMenuItem In itemCollection.OfType(Of ToolStripMenuItem)()
                If item.Name.Equals(name) Then
                    Return item
                ElseIf item.DropDownItems.Count > 0 Then
                    Dim subItem As ToolStripMenuItem = GetItem(name, item.DropDownItems)
                    If subItem IsNot Nothing Then
                        Return subItem
                    End If
                End If
            Next
    
            Return Nothing
        End Function
    
    


    fijate en itemCollection.OfType(Of ToolStripMenuItem)() asi solo hara un for each en los item cuyo tipo sea ToolStripMenuItem

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 23:04
    miércoles, 28 de septiembre de 2011 22:33

Todas las respuestas

  • mmm... como no mencionastes la version del VS que usas te publicare el código...

    la idea seria recorrer el menú hasta encontrar la opción que coincida con el nombre que buscas para que te devuelva la instancia al item del menú para habilitarlo o desabilitarlo.

    ejemplo:

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            ' Enabled/Disable item
            Dim item As ToolStripMenuItem = GetMenuItem("iProductos")
            If item IsNot Nothing Then
                item.Enabled = Not item.Enabled
            End If
    
            item = GetMenuItem("iInventarioActual")
            If item IsNot Nothing Then
                item.Enabled = Not item.Enabled
            End If
    
        End Sub
    
        Private Function GetMenuItem(ByVal name As String) As ToolStripMenuItem
    
            For Each Menu As ToolStripMenuItem In MenuStrip1.Items
                Dim item As ToolStripMenuItem = GetItem(name, Menu.DropDownItems)
                If item IsNot Nothing Then
                    Return item
                End If
            Next
    
            Return Nothing
        End Function
        Private Function GetItem(ByVal name As String, ByVal collection As ToolStripItemCollection) As ToolStripMenuItem
    
            For Each item As ToolStripMenuItem In collection
                If item.Name.Equals(name) Then
                    Return item
                ElseIf item.DropDownItems.Count > 0 Then
                    Dim subItem As ToolStripMenuItem = GetItem(name, item.DropDownItems)
                    If subItem IsNot Nothing Then
                        Return subItem
                    End If
                End If
            Next
    
            Return Nothing
        End Function
    
    


    la función GetMenuItem solo recibe como parametro el nombre del Item del menú a buscar y devuelve un objeto tipo ToolStripMenuItem  y Nothing si no lo encuentra

    la función GetItem() es una función recursiva que busca dentro de cada opción del menú hasta encontrar el item que coincida con el nombre a buscar, recibe como parametro el nombre del item a buscar y la colección ToolStripItemCollection del item del menú donde se esta buscando sin importar la cantidad de sub menús que tenga la opción del menú.

    el ejemplo lo hice en VS2010 si usas esta versión del VS te puedo pasar el projecto de ejemplo.

    ademas sustitute el nombre del menú en la función GetMenu()


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:55
    miércoles, 28 de septiembre de 2011 17:11
  • "FIERIX" preguntó:

    > Como puedo establecer puntualmente esas propiedades ya que no
    > me permite conversion del texto en objeto de menu, este codigo
    > funciona correctamente:
    >
    > La idea es poder hacer algo asi:
    >
    >  Dim Permiso As BC.dtsUsuarios.PermisosUsuarioRow
    >   For Each Permiso In clPermisos (variable de una consulta LINQ)
    >
    >    Dim mnuIndividual As ToolStripMenuItem
    >    mnuIndividual = CType(Permiso.IdControl.ToString, ToolStripMenuItem)
    >    mnuIndividual.Enabled = Permiso.Enabled
    >    mnuIndividual.Visible = Permiso.Visible
    >
    >  Next

    Hola:

    Si he entendido bien el contenido de tu mensaje, deseas referenciar un objeto ToolStripMenuItem existente en un objeto o control MenuStrip, de acuerdo al nombre de usuario que has recuperado de tu base de datos.

    Si es así, como parece ser que estás utilizando consultas LINQ, simplemente te tienes que crear una función (no es necesario, pero queda mejor) que pasándole el nombre del usuario te devuelva su objeto ToolStripMenuItem:

        Private Function GetToolStripMenuItem(ByVal valor As String) As ToolStripMenuItem
    
            Dim query As IEnumerable(Of ToolStripMenuItem) = _
                 From item As ToolStripMenuItem In MenuStrip1.Items.Cast(Of ToolStripMenuItem)() _
                 Where (item.Text.ToLower() = valor.ToLower()) _
                Select item
    
            If (query.ToList.Count > 0) Then
                Return query.ToList(0)
    
            Else
                Return Nothing
    
            End If
    
        End Function
    

    ¿Que no quieres utilizar LINQ? Recorre el clásico bucle For Each de toda la vida:

        Private Function GetToolStripMenuItem(ByVal valor As String) As ToolStripMenuItem
    
            ' Recorremos la colección de elementos del control MenuStrip principal
            ' 
            For Each mnuItem As ToolStripMenuItem In MenuStrip1.Items
    
                ' Comprobamos si el texto especificado se corresponde
                ' con el valor de la propiedad Text del objeto
                ' ToolStripItem actual.
                ' 
                If (mnuItem.Text.ToLower() = valor.ToLower()) Then
                    ' Devolvemos la referencia
                    Return mnuItem
                End If
    
            Next
    
            Return Nothing
    
        End Function
    

    Se comprende que la variable objeto 'MenuStrip1' referencia al objeto MenuStrip principal donde se encuentran los elementos ToolStripMenuItem.

    Cuando desees referenciar el objeto ToolStripMenuItem de un usuario, ejecutarías lo siguiente:

        Dim mnuIndividual As ToolStripMenuItem = GetToolStripMenuItem("Francisco")
    
        If (Not mnuIndividual Is Nothing) Then
            mnuIndividual.Enabled = Permiso.Enabled
            mnuIndividual.Visible = Permiso.Visible
        End If
    

    Espero haber entendido bien tu pregunta. :-)

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.

    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:55
    miércoles, 28 de septiembre de 2011 17:25
  • Muchisimas gracias Marvin por tu pronta respuesta, es de mucha utilidad, estoy trabajando con VS2008.

    Todavia no la pruebo pero por lo que veo la funcion se llama a si misma para poder obtener los subitems inferiores en jeraquía, con lo que no sería necesario agragar otro bucle "For", estoy entendiendo bien?

    Por las respuestas que he recibido parece no haber otra forma que recorrer los items y compararlos con el nombre que he pasado. No se puede acceder directamente como si hiciera:

    Me.mnuOperaciones.Enabled = True

    Si se pudiera convertir una cadena con el nombre del menu al objeto menú sería mas directo pero al parecer en VS2010 tampoco se puede.

    Lo voy a poner en practica, muchas Gracias

    miércoles, 28 de septiembre de 2011 18:21
  • Enrique:

    Muchisimas gracias tu pronta respuesta, tambien me ha sido de mucha utilidad.

    Me gusto el uso de LINQ, no estoy muy avesado en ello. Voy a probarlo pero me gustaría saber de antemano si devuelve todos los menu incluidos los submenu. o solo los que derivan del principal.

    Por las respuestas que he recibido parece no haber otra forma que recorrer los items (o hacer una consulta a la coleccion de menus) y compararlos con el nombre que he pasado. No se puede acceder directamente como si hiciera:

    Me.mnuOperaciones.Enabled = True

    Si se pudiera convertir una cadena con el nombre del menu al objeto menú sería mas directo pero al parecer en VS2010 tampoco se puede.

    Lo voy a poner en practica, muchas Gracias

    miércoles, 28 de septiembre de 2011 18:28
  • "FIERIX" preguntó:

    > me gustaría saber de antemano si devuelve todos los menu incluidos
    > los submenu. o solo los que derivan del principal.

    No. La función 'GetToolStripMenuItem' simplemente devuelve un objeto del tipo ToolStripMenuItem, que entiendo es lo que tu requerías en tu mensaje:

      Dim mnuIndividual As ToolStripMenuItem

    Ese objeto estará referenciando al objeto ToolStripMenuItem que se corresponda con el nombre del usuario. Una vez referenciado el objeto, posteriormente podrás recorrer su colección DropDownItems para acceder a los elementos existentes en dicho objeto.

    > Por las respuestas que he recibido parece no haber otra forma que
    > recorrer los items (o hacer una consulta a la coleccion de menus)
    > y compararlos con el nombre que he pasado. No se puede acceder
    > directamente como si hiciera:
    >
    > Me.mnuOperaciones.Enabled = True

    Que yo sepa, no se puede. Y tampoco creo que sea necesario que existiese. Estamos hablando de referenciar objetos, y en principio, una cadena alfanumérica (un tipo de dato String), no se puede convertir explícita o implícitamente a un objeto del tipo ToolStripMenuItem, al igual que no se puede convertir un valor Integer en un objeto Form, por ponerte un ejemplo un tanto descabellado. :-)

    La solución es la que te hemos propuesto tanto Marvin como yo: crearte tu propia función para tus necesidades, la cual se ejecuta sin ninguna demora, instantáneamente, salvo que tengas, no sé: 3.000 objetos ToolStripMenuItem dentro de un control MenuStrip. :-D

    > Lo voy a poner en practica

    Es lo que mejor que puedes hacer: probar y ver los resultados.

     

     


    Enrique Martínez
      [MS MVP - VB]

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.


    miércoles, 28 de septiembre de 2011 18:48
  • mira.... otra forma para no recorrer todas las opciones del menú tambien podria ser usando Reflection

    ejemplo:

            Dim field As FieldInfo = Me.GetType().GetField("_iProductos", BindingFlags.Instance Or BindingFlags.NonPublic)
            If field IsNot Nothing Then
                Dim itemMenu As ToolStripMenuItem = CType(field.GetValue(Me), ToolStripMenuItem)
                itemMenu.Enabled = Not itemMenu.Enabled
            End If
    
    


    el unico detalle con VBasic es que le agrega el guion bajo (_) al nombre de la variable, así que hay que agregarsela al string a buscar.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 19:56
    miércoles, 28 de septiembre de 2011 18:56
  • Perfecto, Muchas Gracias
    miércoles, 28 de septiembre de 2011 19:35
  • Gracias Marvin, no manejo muy bien el tema de Reflection, pero viendo el ejemplo me queda bastante claro. Voy a probar una combinación entre lo que me pasas y lo de Enrique
    miércoles, 28 de septiembre de 2011 19:55
  • Marvin, el procedimiento GetItem da una excepcion de conversio cuando se encuentra un separador. Como te parece mejor controlarlo o agregar un condicional hay alguna forma de filtrar solo menuitem antes de aplicar el "For" Se me ocurrio esto, que te parece

     

    Private Function GetItem(ByVal pNombre As String, ByVal collection As ToolStripItemCollection) As ToolStripMenuItem

     

    Dim mnu As ToolStripMenuItem

     

    For Each item As ToolStripItem In collection

     

    If item.GetType Is GetType(ToolStripSeparator) Then

     

    GoTo SIGUIENTE

     

    End If

    mnu = item

     

    If mnu.Name.Equals(pNombre) Then

     

    Return mnu

     

    ElseIf mnu.DropDownItems.Count > 0 Then

     

    Dim subItem As ToolStripMenuItem = GetItem(pNombre, mnu.DropDownItems)

     

    If subItem IsNot Nothing Then

     

    Return subItem

     

    End If

     

    End If

    SIGUIENTE:

     

    Next

     

    Return Nothing

     

    End Function
    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 22:27
    miércoles, 28 de septiembre de 2011 22:26
  • claro, tambien lo podrias resolver asi:

        Private Function GetItem(ByVal name As String, ByVal itemCollection As ToolStripItemCollection) As ToolStripMenuItem
    
            For Each item As ToolStripMenuItem In itemCollection.OfType(Of ToolStripMenuItem)()
                If item.Name.Equals(name) Then
                    Return item
                ElseIf item.DropDownItems.Count > 0 Then
                    Dim subItem As ToolStripMenuItem = GetItem(name, item.DropDownItems)
                    If subItem IsNot Nothing Then
                        Return subItem
                    End If
                End If
            Next
    
            Return Nothing
        End Function
    
    


    fijate en itemCollection.OfType(Of ToolStripMenuItem)() asi solo hara un for each en los item cuyo tipo sea ToolStripMenuItem

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    • Marcado como respuesta FIERIX miércoles, 28 de septiembre de 2011 23:04
    miércoles, 28 de septiembre de 2011 22:33
  • Buenisimo, de esa forma me gusta mas.

    Otra pregunta, para insertar codigo aca y que quede bien, hay que hacerlo con el boton especifico si no queda mal?

    miércoles, 28 de septiembre de 2011 22:55
  • Buenisimo, de esa forma me gusta mas.

    Otra pregunta, para insertar codigo aca y que quede bien, hay que hacerlo con el boton especifico si no queda mal?

    así es, como lo habras nota con el codigo que publicastes y lo notaras con el codigo que he publicado.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 29 de septiembre de 2011 2:06