none
¿Cómo asignar "grupos" (propiedad tipo colección) a "items" (propiedad tipo colección), igual que en un ListView? RRS feed

  • Pregunta

  • De nuevo yo por aquí. Saludos.

    Dejénme explicar qué significa mi pregunta, por si no se entiende.

    Como saben, los ListViews contienen varias propiedades tipo colección (Columns, Groups, Items), y específicamente la colección Items permite asociarse con la colección Groups. Al cargar un item, este contiene una propiedad llamada Group que muestra todos los elementos asignados en Groups.

    Muy bien, es justo eso lo que quiero hacer. En mi UserControl tengo una propiedad Groups y otra Items. Ambas son tipo colección; la primera almacena elementos UserControlGroup y la segunda elementos UserControlItem, que son clases creadas por mí. Pues bien, cada UserControlItem contiene una propiedad Group tipo UserControlGroup, que se supone es para asignar un elemento UserControlGroup de la colección Groups, pero es ahí donde tengo el problema: no sé cómo hacer para detectar los elementos de la colección Groups al momento de asignar la propiedad UserControlItem.Group; es decir, me aparece vacía, aunque existan elementos en Groups.

    Así que mi pregunta es: ¿cómo logro que mis elementos UserControlGroup se vean al desplegar la propiedad UserControlItem.Group?

    Algo interesante es que, si asigno una propiedad tipo Label en un UserControl, me pasa lo mismo, hasta que inserto un Label en el mismo formulario donde tengo ese UserControl; entonces puedo asignar ese Label a la propiedad; y si tengo 5 Label en el formulario, los 5 son visibles desde la propiedad, y puedo elegir cualquiera de ellos. Esto me deja ver que una propiedad tipo Label toma automáticamente los elementos Label de la colección de controles del formulario (Form1.Controls), y eso es justo lo que quiero que ocurra con mi propiedad UserControlItem.Group: que me tome automáticamente los elementos de la colección UserControl.Groups.

    Agradezco sus respuestas.


    Something new to learn everyday.
    viernes, 29 de julio de 2011 21:38

Respuestas

  • ok... veamos entonces,

    lastimosamente tendras que hacer que las clases UserControlGroup y UserControlItem hereden de Component ya que de lo contrario no funcionara, por lo menos a mi me marca error, claro!!!! eso falta que ver si lo estas haciendo de la misma manera que lo estoy haciendo yo en el projecto de ejemplo que te paso.

    segun mi ejemplo:

    <ToolboxItem(False), DesignTimeVisible(False)> _
    Public Class UserControlItem
      Inherits Component
    
      Private _group As UserControlGroup
      Private _property1 As String
    
      Sub New()
        _property1 = ""
      End Sub
    
      <DefaultValue(GetType(Nullable), "Nothing")> _
      Public Property Group() As UserControlGroup
        Get
          Return _group
        End Get
        Set(ByVal value As UserControlGroup)
          _group = value
        End Set
      End Property
      <DefaultValue("")> _
      Public Property Property1() As String
        Get
          Return _property1
        End Get
        Set(ByVal value As String)
          _property1 = value
        End Set
      End Property
    End Class
    

    ahora, teniendo ya bien definida la clase para que funcione, por cierto motivo que desconosco y por falta de tiempo no te lo resuelvo en este projecto de ejemplo, es que al momento de editar la colección Grupos o Items el editor de colecciones no logra obtener la descripcion de cada propiedad de la clase por ende no lo utilize y lo que hice fue crear dos metodos en el Smart Tag para poder agregar Items y Grupos a los colecciones.

      Friend Sub OnAddGroup()
        Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim t As DesignerTransaction = host.CreateTransaction("Agregando grupo")
        Dim newGroup As UserControlGroup = CType(host.CreateComponent(GetType(UserControlGroup)), UserControlGroup)
        Grupos.Insert(Grupos.Count, newGroup)
        t.Commit()
      End Sub
      Friend Sub OnAddItem()
        Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim t As DesignerTransaction = host.CreateTransaction("Agregando Item")
        Dim newGroup As UserControlItem = CType(host.CreateComponent(GetType(UserControlItem)), UserControlItem)
        Items.Insert(Items.Count, newGroup)
        t.Commit()
      End Sub
    
    

    tomando como ejemplo mi NetBarControl yo no tube necesidad de indicarle un TypeConverter a la Coleccion Groups, en cambio aqui en VB ni idea de porque no lo logra reconocer ni aplicando TypeConvert, algo estare aplicando mal pero luego lo revisare.

    asi que aqui te dejo el projecto para que lo revises

    en espera de tus comentarios.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 11 de agosto de 2011 17:39
    Moderador
  • Es extraño. Acabo de revisar en un ListView y los elementos ListViewGroup no heredan de Component, porque no se ven en el listado de la ventana de propiedades. Solo los elementos ColumnHeader del ListView son Component, pues son los únicos que se ven allí. Aún así los grupos son visibles desde los Items. Lamentablemente parece que no diste con la solución. :(
    Something new to learn everyday.

    lo otro que se me ocurre es que cambies el editor para la propieda Grupo en la clase UserControlItem para que muestres un ListBox con la lista de grupos definidos en el control, ya que mencionas que si persisten estas clases en el archivo Designer.vb porque he intentado y nope no veo como lograstes que persistieran sin ser componentes y sin usar CodeDomSerializer.

    claro!!!!... aplicarlo de esta manera podria significar hacer más cambios en tu control.

    ejemplo:

     

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    viernes, 12 de agosto de 2011 2:56
    Moderador

Todas las respuestas

  • mmmm... este es un tema no muy facil de explicar ya que cada quien crea sus controles según sea su necesidad y tal funcionamiento aunque paresca igual puede variar entre un control y otro.

    Mencionas que Groups y Items son propiedades tipo colección, por ende no detectaran automaticamente los controles del mismo tipo de ellas dentro del control ya que no funcionan igual a la observacion que mencionas de crear una propiedad Label ya que una propiedad Label es unica asi que si agregas un label a tu control esta propiedad te mostrara la lista de Label dentro del control para que seleccione una, si cambias esta propiedad tipo Label a Label Collection veras que ya no las detectara.

    estas collecciones Groups e Items solo mostrara los controles tipo UserControlGroup y UserControlItems que se hayan agregado o creado usando el editor de la propiedad en tiempo de diseño o desde codigo asignadas a cada Item de la colección, y en Designer.vb del formulario donde uses el control podras ver los controles UserControlGroup definidos y en la Propiedad Groups de tu control podras que hace referencia a estos

    por ejemplo:

    userControl.Groups.AddRange(new UserControlGroups[] { userControlGroup1, userControlGroup2, userControlGroup3 });

    esto podria cambiar segun la logica de funcionamiento de cada control con respecto a presistir, en mi caso lo podras ver en el control NetBarControl y TextEditor, la forma aunque paresca igual no funcionan igual con respecto a los botones en el control TextEditor y los grupos en el control NetBarControl.

    así que faltaria que ver cual sera la funcionalidad o logica que le quieres dar a tu control para poder darte una mano.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    martes, 2 de agosto de 2011 4:44
    Moderador
  • Veo que me has malinterpretado Marvin. Si te fijas, yo no sugerí detectar los elementos de la colección en otra propiedad colección, sino en una propiedad tipo elemento-colección. Me explico:

    Tengo la colección UserControl.Groups que almacena elementos UserControlGroup.

    También tengo la colección UserControl.Items que almacena elementos UserControlItem.

    Los elementos de las dos colecciones son clases creadas por mí. Cada colección se llena por separado. Eso está bajo control.

    Ahora bien, cada elemento UserControlItem tiene una propiedad Group tipo UserControlGroup (no tipo colección), y es a través de esta que quiero detectar los elementos contenidos en UserControl.Groups que son del mismo tipo.

    Como dije al inicio, es exactamente igual al ListView: este tiene una propiedad Groups, otra Items (ambas colecciones), y en cada elemento de Items (ListViewItem) se pueden ver los elementos de Groups a través de la propiedad ListViewItem.Group, que no es colección, sino del mismo tipo que compone la colección ListView.Groups (creo que ListViewGroup).

    Yo lo tengo igual; solo me hace falta detectar los elementos UserControlGroup (contenidos en UserControl.Groups) a través de mi propiedad UserControlItem.Group, que también es del tipo UserControlGroup (el mismo tipo que almacena la colección UserControl.Groups).

    ¿Se entiende ahora?

     


    Something new to learn everyday.
    miércoles, 3 de agosto de 2011 21:22
  • ok, intentare reproducir tu problema, pero para esto necesito saber, UserControlGroup y UserControlItem de que controles hereran? o son clases que no hereran de ningun control?

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor




    jueves, 4 de agosto de 2011 21:57
    Moderador
  • Disculpa la tardanza. Hasta ahorita puedo responder.

    Esas clases de las que hablo no heredan, son clases sencillas que solo tienen unas cuantas propiedades.


    Something new to learn everyday.
    jueves, 11 de agosto de 2011 1:36
  • Disculpa la tardanza. Hasta ahorita puedo responder.

    Esas clases de las que hablo no heredan, son clases sencillas que solo tienen unas cuantas propiedades.


    Something new to learn everyday.

    ok, unas ultimas preguntas para estar completamente bien informado...

    ¿Cuando creas los items para la coleccion UserControlGroup y UserControlItem, estas clases persistente en el archivo ej: Form1.Designer.vb?

    ¿Cuando en tu pregunta inicial dice: ¿cómo logro que mis elementos UserControlGroup se vean al desplegar la propiedad UserControlItem.Group?, como haces para seleccionar un elemento UserControlItem en tiempo de diseño, ya que estos deberian ser mostrados (dibujados) en la superficie del Control para que el usuario (programador) lo pueda seleccionar y cambiar algunas propiedades (en dado caso que el usuario (programador) pueda manipularlas en tiempo de diseño?

    si pudieras mostrar imagenes de tu control, imagenes que muestren el funcionamiento de tal control para tener todo más claro.

    de que se puede se puede por acabo de hacer una pequeña prueba con mi control NetBarControl y si se puede sin hacer nada extra, pero todo dependera de como estes persistiendo estos controles UserControlGroup y UserControlItem en el formulario o UserControl donde uses este control.

    a la espera de tu comentario.

    Salu2,

     


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 11 de agosto de 2011 1:56
    Moderador
  • Sí. Ambos elementos de la colección (UserControlGroup y UserControlItem) se registran en la clase Form1.Designer.vb; los cambios que haga en cada item de cualquiera de las dos colecciones queda registrado en esta sección de código, igual que ocurre con un ListView. Por eso pensé que no tendría problema para visualizarlos desde otra propiedad. ¿Será que debo asignarle algún atributo de System.ComponentModel para que sea visible? Yo estuve revisando los mismos, y me pareció que algunos tienen que ver con eso. Pero no logré conseguirlo.
    Something new to learn everyday.
    jueves, 11 de agosto de 2011 5:52
  • ok... veamos entonces,

    lastimosamente tendras que hacer que las clases UserControlGroup y UserControlItem hereden de Component ya que de lo contrario no funcionara, por lo menos a mi me marca error, claro!!!! eso falta que ver si lo estas haciendo de la misma manera que lo estoy haciendo yo en el projecto de ejemplo que te paso.

    segun mi ejemplo:

    <ToolboxItem(False), DesignTimeVisible(False)> _
    Public Class UserControlItem
      Inherits Component
    
      Private _group As UserControlGroup
      Private _property1 As String
    
      Sub New()
        _property1 = ""
      End Sub
    
      <DefaultValue(GetType(Nullable), "Nothing")> _
      Public Property Group() As UserControlGroup
        Get
          Return _group
        End Get
        Set(ByVal value As UserControlGroup)
          _group = value
        End Set
      End Property
      <DefaultValue("")> _
      Public Property Property1() As String
        Get
          Return _property1
        End Get
        Set(ByVal value As String)
          _property1 = value
        End Set
      End Property
    End Class
    

    ahora, teniendo ya bien definida la clase para que funcione, por cierto motivo que desconosco y por falta de tiempo no te lo resuelvo en este projecto de ejemplo, es que al momento de editar la colección Grupos o Items el editor de colecciones no logra obtener la descripcion de cada propiedad de la clase por ende no lo utilize y lo que hice fue crear dos metodos en el Smart Tag para poder agregar Items y Grupos a los colecciones.

      Friend Sub OnAddGroup()
        Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim t As DesignerTransaction = host.CreateTransaction("Agregando grupo")
        Dim newGroup As UserControlGroup = CType(host.CreateComponent(GetType(UserControlGroup)), UserControlGroup)
        Grupos.Insert(Grupos.Count, newGroup)
        t.Commit()
      End Sub
      Friend Sub OnAddItem()
        Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost)
        Dim t As DesignerTransaction = host.CreateTransaction("Agregando Item")
        Dim newGroup As UserControlItem = CType(host.CreateComponent(GetType(UserControlItem)), UserControlItem)
        Items.Insert(Items.Count, newGroup)
        t.Commit()
      End Sub
    
    

    tomando como ejemplo mi NetBarControl yo no tube necesidad de indicarle un TypeConverter a la Coleccion Groups, en cambio aqui en VB ni idea de porque no lo logra reconocer ni aplicando TypeConvert, algo estare aplicando mal pero luego lo revisare.

    asi que aqui te dejo el projecto para que lo revises

    en espera de tus comentarios.

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    jueves, 11 de agosto de 2011 17:39
    Moderador
  • Es extraño. Acabo de revisar en un ListView y los elementos ListViewGroup no heredan de Component, porque no se ven en el listado de la ventana de propiedades. Solo los elementos ColumnHeader del ListView son Component, pues son los únicos que se ven allí. Aún así los grupos son visibles desde los Items. Lamentablemente parece que no diste con la solución. :(
    Something new to learn everyday.
    jueves, 11 de agosto de 2011 22:49
  • Es extraño. Acabo de revisar en un ListView y los elementos ListViewGroup no heredan de Component, porque no se ven en el listado de la ventana de propiedades. Solo los elementos ColumnHeader del ListView son Component, pues son los únicos que se ven allí. Aún así los grupos son visibles desde los Items. Lamentablemente parece que no diste con la solución. :(
    Something new to learn everyday.

    jajajajaja...

    tu has tocado un tema  un poco dificil de explicar ListViewGroup no heredan de Component, Ok Estoy deacuerdo, tuve la curiosidad y agregue un ListView y le agregue Grupos y la sorpresa es en el archivo Designer.vb

    Dim ListViewGroup1 As System.Windows.Forms.ListViewGroup = New System.Windows.Forms.ListViewGroup("ListViewGroup", System.Windows.Forms.HorizontalAlignment.Left)
    Dim ListViewGroup2 As System.Windows.Forms.ListViewGroup = New System.Windows.Forms.ListViewGroup("ListViewGroup", System.Windows.Forms.HorizontalAlignment.Left)
    Dim ListViewGroup3 As System.Windows.Forms.ListViewGroup = New System.Windows.Forms.ListViewGroup("ListViewGroup", System.Windows.Forms.HorizontalAlignment.Left)

    estas declaraciones de variables estan al inicio, esto me dice que el ListView usa CodeDomSerializer para persistir estas variables y como veras estan declaradas y definidas, para poder hacer tu esto entonces tendras que implementar CodeDomSerializer para tu control para poder persistir de esta manera tus clases.

    como podras ver a diferencia de otros controles ,que se crea la variable y luego mas abajo define las propiedad de estas que han sido cambiadas...

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    viernes, 12 de agosto de 2011 0:07
    Moderador
  • Es extraño. Acabo de revisar en un ListView y los elementos ListViewGroup no heredan de Component, porque no se ven en el listado de la ventana de propiedades. Solo los elementos ColumnHeader del ListView son Component, pues son los únicos que se ven allí. Aún así los grupos son visibles desde los Items. Lamentablemente parece que no diste con la solución. :(
    Something new to learn everyday.

    lo otro que se me ocurre es que cambies el editor para la propieda Grupo en la clase UserControlItem para que muestres un ListBox con la lista de grupos definidos en el control, ya que mencionas que si persisten estas clases en el archivo Designer.vb porque he intentado y nope no veo como lograstes que persistieran sin ser componentes y sin usar CodeDomSerializer.

    claro!!!!... aplicarlo de esta manera podria significar hacer más cambios en tu control.

    ejemplo:

     

    Salu2,


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    viernes, 12 de agosto de 2011 2:56
    Moderador
  • Es extraño. Acabo de revisar en un ListView y los elementos ListViewGroup no heredan de Component, porque no se ven en el listado de la ventana de propiedades. Solo los elementos ColumnHeader del ListView son Component, pues son los únicos que se ven allí. Aún así los grupos son visibles desde los Items. Lamentablemente parece que no diste con la solución. :(
    Something new to learn everyday.

    Hola Jason,

    me dejo picado este comportamiento en VB de no poder persistir estas clases en el archivo "Designer.vb" y problemas que tube para poder heredar de CollectionEditor (mi fuerte es C#) y en la definición de las coleciones para las clases, ya encontre el problema, así que aqui te paso el projecto para que lo revises.

    el objetivo y problema que reportas es que la propiedad Grupo en la clase UserControlItem no detecta las clases UserControlGroup dentro de la coleccion UserControlGroupCollection del control, no las va a detectar porque realmente no son componentes, internal mente son manejadas como variables por el diseñador, a como pude comprender el comportamiento, por ende la solución es aplicar un editor para esta propieda.

    para poder obtener la lista de grupos desde los items lo que hice fue crear una propiedad interna (Friend) en la clase UserControlItem con la idea de que la clase UserControlItem sepa quien es su contenedor (Propietario), el propietario (Owner) se pasa en el constructor de la clase, tambien veras que la clase UserControlItemCollection y UserControlGroupCollection implementan este propietario.

    ahora... para poder pasar el propietario al momento de estar editando la collecion con el editor de colecion he creado una clase que hereda de CollectionEditor y sobre escrito algunos metodos y funciones para que funcione sin problema.

    revisalo y me avisas

    Salu2,

     

     


    Marvin E. Pineda

      ComboBoxMultiColumns

      NetBarControl

      TextEditor



    viernes, 12 de agosto de 2011 16:20
    Moderador