Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: <ИΘZIЭ(ŦB> en 10 Marzo 2011, 18:05 pm



Título: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 10 Marzo 2011, 18:05 pm
Qué tal compañeros de foro! Hace tiempo que no pasaba por aqui. Saludos...

Les cuento que hace unos meses aprendi a crear mis propios controles personalizados (custom control), y si que ha sido provechoso. Es la mejor solucion cuando se quiere modificar o agregar propiedades a un control predefinido, o bien crear uno totalmente a la medida.
Pues bien, esto ultimo es justamente mi caso. Estoy creando un panel de botones, al que pueda ir cargandole items tal como se hace en un ListView, por ejemplo, solo que en este caso los items seran botones, que por cierto también son creados por mi.
En fin, para ello me cree una propiedad tipo lista (List (Of CrystalButton)), que se supone usaré para cargar los botones al panel. Pues bien, es justo ahi donde tengo el problema, pues no sé como asociar la inclusion de items a algun evento. ¿Para qué quiero eso? Pues porque es justo ahi donde debo incluir el codigo que me agregue el nuevo item al control e indique su posicion. De no hacer eso sólo puedo cargar ítems en la propiedad tipo lista, pero los botones no se agregan a mi control.
¿Me echan la mano?

Ah! Olvidé mencionar que uso el Visual Studio 2008, y estoy programando en Visual Basic.


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: Novlucker en 10 Marzo 2011, 19:16 pm
Bueno, lo primero que se me ocurre es que crees tu propio customlist heredando de list<t> y sobrecargues el método add agregando un evento :D

Saludos


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: SRVAM en 10 Marzo 2011, 19:18 pm
No entiendo muy bien como lo tienes hecho, por lo que yo he entendido, has heredado tu control de un Listview verdad??
Si es asi, prueba a suscribirte al evento "ItemInserted".
Si eso no te funciona pon el codigo de tu control y asi podre intentar ayudarte mas ;)

Un saludo


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: Novlucker en 10 Marzo 2011, 19:24 pm
Lo que entiendo es que tiene un panel en el que uno de sus atributos es una lista generica de botones, y quiere que al agregar un botón en esa lista, se dispare un evento que lo ubique en el panel :P

Puede que yo haya entendido mal :xD

Saludos


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: SRVAM en 10 Marzo 2011, 19:40 pm
Lo que entiendo es que tiene un panel en el que uno de sus atributos es una lista generica de botones, y quiere que al agregar un botón en esa lista, se dispare un evento que lo ubique en el panel :P

Puede que yo haya entendido mal :xD

Saludos

Tienes razon Novluker, se refiere a un panel xDD yo lei listview y claro, ya me lie pensando en eso jajaja

Otra cosa que se peude intentar es que en vez de agregar los botones como items de un list, que se agregen a la coleccion de controles del panel y se suscriba al evento "ControlAdded" praa saber cuando se ha añadido un boton a la lista de controles del panel.



Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 11 Marzo 2011, 04:20 am
Bien. Veo que ya entienden lo que quiero, y me han "sugerido" qué hacer. El asunto es que de verdad no tengo idea de cómo hacer lo que dicen. Por ejemplo, ¿cómo 'suscribo' la adición de botones a ese evento "ControAdded"? De verdad es primera vez que intento hacer un control de ese tipo, así que necesito detalles.
Otra cosa: mi control no es un Panel; es decir, no hereda del control Panel. Simplemente funcionará cómo un panel porque contendrá una serie de botones que el usuario irá cargando.


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: SRVAM en 11 Marzo 2011, 13:48 pm
Para que podamos ayudarte mejor lo suyo seria que pudieses el codigo de tu control.

Sino hereda de un panel del que peudas coger eventos tipo ControlAdded puedes crearte tu propio evento y hacer que este salte cuando agregues un nuevo elemento a la lista.

pero es que sin ver tu codigo no se me ocurre mucho mas que decirte para ayudarte.

un saludo


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 11 Marzo 2011, 18:11 pm
Entiendo. El asunto es que no tengo código alguno todavía. Lo único que hice fue agregar un nuevo UserControl al proyecto. Cómo saben, esto me muestra un cuadro vacío en la ventana de diseño. Luego me fui al código y agregué una nueva propiedad tipo lista (como ya mencioné), y fue entonces cuando noté que no sabía que más hacer.
Así pues, hasta ahora sólo tengo esta propiedad llamada Items, a la que puedo agregar elementos sin problema desde el modo diseño. Sólo me hace falta captar la inclusión de los ítems en la propiedad, para agregarlos al UserControl.


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 11 Marzo 2011, 18:17 pm
Hola,

Es un poco largo, pero es la manera más sexy de y elegante de hacerlo:

1) En vez de utilizar List(Of CrystalControl), crea una clase que herede de Collection(Of T).

2) En esa clase que la llamaría CrystalControlCollection, tienes que crear un evento público (algo como ControlAdded) con un EventHandler(Of CrystalControlEventArgs).

3)CrystalControlEventArgs es otra clase que hereda de EventArgs con una propiedad pública de tipo CrystalControl que se llame Item (u otro nombre que quieras)

4) Luego haces override del método InsertItem en la clase CrystalControlCollection y ahi llamas al evento ControlAdded (con RaiseEvent en vb.net) en donde le pasas el control que se está añadiendo.

5) Sustituyes la lista por CrystalControlCollection, y te suscribes al evento ControlAdded :)

Puedes hacer muchas más cosas como cuando sacas un control de la lista llamar a otro evento en donde realmente sacas el control del UI. Esto se llama event driven development , creo.

Un saludo!


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: Novlucker en 11 Marzo 2011, 18:47 pm
Que pesado! es como en el code del bot irc que saltaba por todas las páginas buscando eventos :xD

Es parecido a lo que puse al principio :xD la diferencia esta en que había obviado el tema de que los métodos de list no se pueden sobreescribir (por eso la sobrecarga), y lo del customeventhandler. ¿Podemos dar por buena mi respuesta? Di que si, di que si :D

Y pasate más por el foro, que sino sigo sugiriendo chapuzas :xD

Saludos



Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 11 Marzo 2011, 19:28 pm
Claro que esta bien tu respuesta xD Ahora es que la leo! Es que hoy llegué cansado y solo leí el primer post y respondí. Ahora es que leí todo completo :P

Y si, el bot está programado en event driven.

 :xD

Además me paso todos los días por el foro  :¬¬


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 11 Marzo 2011, 19:39 pm
Bien. Agradezco de verdad toda la explicación, aunque un poco compleja para mí. Igual hice todo lo que enumeró, excepto por el más importante, el de suscribirse al evento ControlAdded, que es justo lo que me hace falta saber. ¿Será posible que escriban un ejemplo del código que suscribe un evento de mi UserControl al evento ControlAdded de la clase CrystalControlCollection? Por favor...


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: raul338 en 11 Marzo 2011, 19:49 pm
Atencion: Puede que lo que diga sea disparate pero acabo de quemarme el cerebro con un algoritmo.

Y si inventas tu propia funcion AgregarBoton y ahi lo ubicas? O haz que primero agregue los botones y en una funcion "UbicarBotones" haces lo que tengas que hacer para mostrarlos :P

Seria mas facil que crear una copia personalizada de List(Of t) o similar :P


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 11 Marzo 2011, 19:55 pm
@<ИΘZIЭ(ŦB>
Te recomiendo que te leas esto:

http://carlossantos.wordpress.com/2008/01/20/events-delegates/
http://foro.elhacker.net/net/tutorial_delegados_en_net_c-t301022.0.html (para C# pero es básicamente lo mismo)

@Raul: >_> eso es un poco caimán.


Código
  1. #DEFINE CAIMAN "Ordinario"
xD


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: SRVAM en 11 Marzo 2011, 19:59 pm
Código
  1. #DEFINE CAIMAN "Ordinario"
xD

 ;-) ;-)


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: seba123neo en 12 Marzo 2011, 01:45 am
haber si me queda claro lo que queres hacer, simplemente es un usercontrol que crea botones ? o sea yo le digo que me cree 10 botones y el usercontrol muestra eso ? y que cada uno tenga su evento no ?


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 12 Marzo 2011, 04:54 am
Veo que aún hay algunas dudas. Intentaré explicar todo de nuevo.

Decidí crear un control (UserControl) que funcione como un contenedor de Botones. Sé bien que eso puedo hacerlo con un Panel normal, agregandole Botones desde la ToolBox, pero no quiero hacerlo así. Quiero hacerlo en mi propio control desde una propiedad tipo lista o colección llamada Items. En modo diseño, dicha propiedad me muestra la palabra "(Collection)" seguida de un pequeño botón con tres puntitos que al oprimirse me muestra mi colección de botones en una ventana, con un botón Add y otro Remove. Con Add voy cargando botones a la colección y asignándole sus respectivas propiedades a cada uno. Una vez terminada la inclusión, oprimo el botón Ok de la ventana, quedando lista la colección de botones. Si vuelvo a oprimir el botón con tres puntitos veo la colección ya creada. Hasta ahí voy perfecto.
Ahora bien, lo que me hace falta es que al oprimir el botón Ok en la ventana de la colección se me carguen los botones al UserControl. Necesito captar el cambio en la colección para llamar al código que me agrega y ordena los botones en el UserControl. ¿Cómo lo hago?


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 13 Marzo 2011, 05:57 am
Les cuento que he estado dándome duro con mi control a fin de hallar la respuesta a mi incógnita, y se podría decir que he tenido éxito. No obstante, hay detalles que aún me gustaría aclarar.
Respecto a la pregunta anterior, ya noté cuándo detectar el cambio de la propiedad tipo colección, aunque me pareció muy raro. Al principio, cuando la creé, supuse que dicho cambio ocurriría en el bloque Set de la propiedad, pero le puse un Breakpoint y no pasaba nada; es decir que la inclusión de un nuevo botón en la colección no estaba relacionado con Set. Por eso estaba preguntando cómo podía detectarla.
Sin embargo, posteriormente noté (usando otro Breakpoint) que al agregar o remover un ítem de la colección se ejecutaba el bloque Get de la propiedad; no entendí por qué. Pero igual escribí allí el llamado al método que agrega y ordena los botones en mi control.
No obstante, mis problemas no acabaron allí. Por un lado, vi que una vez incluidos los botones en mi control podía manipularlos; o sea, moverlos y de hecho sacarlos del control. Eso no me gustó. Y por otro lado, empecé a tener un error con algo llamado SerializableAtribute. Eso me condujo a esta página (entre otras) que me sirvió de mucho: http://msdn.microsoft.com/es-es/library/ms171731.aspx. Gracias a ese ejemplo descubrí que ese extraño caso de que al cambiar la colección se ejecutara Get en vez de Set ocurre sólo al definir la propiedad como lista o colección; pero al definirla como Array se corrige la eventualidad. Es decir que ahora que tengo la propiedad tipo Array, se ejecuta Set al cambiar la colección y presionar el botón Ok en el editor de colecciones. No obstante, sigo sin entender por qué con List y Collection no. Si alguien lo sabe...
Y lo otro que quiero saber es cómo puedo cargar los botones a mi control sin que puedan manipularse. Quiero que sean como los que uno crea directamente en un UserControl, que no son manipulables desde donde usa el mismo. ¿Alguna idea?


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 13 Marzo 2011, 15:15 pm
Citar
Respecto a la pregunta anterior, ya noté cuándo detectar el cambio de la propiedad tipo colección, aunque me pareció muy raro. Al principio, cuando la creé, supuse que dicho cambio ocurriría en el bloque Set de la propiedad, pero le puse un Breakpoint y no pasaba nada; es decir que la inclusión de un nuevo botón en la colección no estaba relacionado con Set. Por eso estaba preguntando cómo podía detectarla.

Correcto, no va a pasar nada porque estás cambiando valores del List no estas cambiando el List como tal.

En el bloque get se detiene no porque estas cambiando la coleccion sino porque pides la colección para agregar, eliminar, o lo que sea hacia el objecto como tal. Pudo haber sido cualquier otra clase, no necesariamente una lista y obtendrías el mismo comportamiento.

Tu puedes hacerlo como quieras, pero la manera que te habíamos dicho es la más sexy.

Un saludo. :)


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 13 Marzo 2011, 18:17 pm
Claro hermano. De hecho, hice todo lo que sugeriste, pero no me dijiste cómo detectar el cambio de la colección. Nunca supe cómo implementar el evento de la colección en el UserControl. Por eso busqué otras fuentes.


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: Novlucker en 13 Marzo 2011, 18:23 pm
Te lo dijo aquí :rolleyes:

@<ИΘZIЭ(ŦB>
Te recomiendo que te leas esto:

http://carlossantos.wordpress.com/2008/01/20/events-delegates/
http://foro.elhacker.net/net/tutorial_delegados_en_net_c-t301022.0.html (para C# pero es básicamente lo mismo)


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 13 Marzo 2011, 19:51 pm
Ya lo leí hermano, pero no entendí cómo aplicarlo a mi caso. Gracias.


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 13 Marzo 2011, 20:14 pm
Para detectar el cambio te dije que sobreescribieras el InsertItem .. :)


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 19 Marzo 2011, 05:06 am
Sigo insistiendo aquí porque todavía tengo algunos problemas con la propiedad tipo colección.
Antes que nada, debo decir que ya pude detectar el cambio en la colección. En efecto, había que lanzar el evento público ControlAdded desde el evento InsertItem sobreescrito de la colección, y luego suscribirse al mismo desde el UserControl contenedor, cómo sugirieron. Ahora bien, ¿cómo se hace la suscripción? Estuve esperando esa respuesta todo el tiempo, más nunca me llegó; apenas vine a saberlo hace unos minutos.
Resulta que lo único que había que hacer era agregar WithEvents a la declaración de la variable que complementa a la propiedad colección, y luego agregar Handles variable.ControlAdded al método que incluye y ordena los botones.
Ahora bien, como mencioné antes, mis problemas no han terminado, así que requiero de su pericia nuevamente.
Resulta que, por alguna extraña razón que desconozco, el evento RemoveItem no se ejecuta al remover un ítem de la colección. De verdad no lo entiendo. Hice lo mismo que con InsertItem y nada que me da resultado, pues noté que la compilación no entra en el bloque RemoveItem cuando remuevo un ítem de la colección. ¿Por qué pasa eso?


Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: [D4N93R] en 19 Marzo 2011, 13:19 pm
Eso no debería pasar. Podrías postear el codigo del Collection.

Un saludo!

PD: Encontré esto en MSDN:

Código
  1. Imports System
  2. Imports System.Collections.Generic
  3. Imports System.Collections.ObjectModel
  4.  
  5. Public Class Dinosaurs
  6.    Inherits Collection(Of String)
  7.  
  8.    Public Event Changed As EventHandler(Of DinosaursChangedEventArgs)
  9.  
  10.    Protected Overrides Sub InsertItem( _
  11.        ByVal index As Integer, ByVal newItem As String)
  12.  
  13.        MyBase.InsertItem(index, newItem)
  14.  
  15.        RaiseEvent Changed(Me, New DinosaursChangedEventArgs( _
  16.            ChangeType.Added, newItem, Nothing))
  17.    End Sub
  18.  
  19.    Protected Overrides Sub SetItem(ByVal index As Integer, _
  20.        ByVal newItem As String)
  21.  
  22.        Dim replaced As String = Items(index)
  23.        MyBase.SetItem(index, newItem)
  24.  
  25.        RaiseEvent Changed(Me, New DinosaursChangedEventArgs( _
  26.            ChangeType.Replaced, replaced, newItem))
  27.    End Sub
  28.  
  29.    Protected Overrides Sub RemoveItem(ByVal index As Integer)
  30.  
  31.        Dim removedItem As String = Items(index)
  32.        MyBase.RemoveItem(index)
  33.  
  34.        RaiseEvent Changed(Me, New DinosaursChangedEventArgs( _
  35.            ChangeType.Removed, removedItem, Nothing))
  36.    End Sub
  37.  
  38.    Protected Overrides Sub ClearItems()
  39.        MyBase.ClearItems()
  40.  
  41.        RaiseEvent Changed(Me, New DinosaursChangedEventArgs( _
  42.            ChangeType.Cleared, Nothing, Nothing))
  43.    End Sub
  44.  
  45. End Class
  46.  
  47. ' Event argument for the Changed event.
  48. '
  49. Public Class DinosaursChangedEventArgs
  50.    Inherits EventArgs
  51.  
  52.    Public ReadOnly ChangedItem As String
  53.    Public ReadOnly ChangeType As ChangeType
  54.    Public ReadOnly ReplacedWith As String
  55.  
  56.    Public Sub New(ByVal change As ChangeType, ByVal item As String, _
  57.        ByVal replacement As String)
  58.  
  59.        ChangeType = change
  60.        ChangedItem = item
  61.        ReplacedWith = replacement
  62.    End Sub
  63. End Class
  64.  
  65. Public Enum ChangeType
  66.    Added
  67.    Removed
  68.    Replaced
  69.    Cleared
  70. End Enum
  71.  
  72. Public Class Demo
  73.  
  74.    Public Shared Sub Main()
  75.  
  76.        Dim dinosaurs As New Dinosaurs
  77.  
  78.        AddHandler dinosaurs.Changed, AddressOf ChangedHandler
  79.  
  80.        dinosaurs.Add("Psitticosaurus")
  81.        dinosaurs.Add("Caudipteryx")
  82.        dinosaurs.Add("Compsognathus")
  83.        dinosaurs.Add("Muttaburrasaurus")
  84.  
  85.        Display(dinosaurs)
  86.  
  87.        Console.WriteLine(vbLf & "IndexOf(""Muttaburrasaurus""): {0}", _
  88.            dinosaurs.IndexOf("Muttaburrasaurus"))
  89.  
  90.        Console.WriteLine(vbLf & "Contains(""Caudipteryx""): {0}", _
  91.            dinosaurs.Contains("Caudipteryx"))
  92.  
  93.        Console.WriteLine(vbLf & "Insert(2, ""Nanotyrannus"")")
  94.        dinosaurs.Insert(2, "Nanotyrannus")
  95.  
  96.        Console.WriteLine(vbLf & "dinosaurs(2): {0}", dinosaurs(2))
  97.  
  98.        Console.WriteLine(vbLf & "dinosaurs(2) = ""Microraptor""")
  99.        dinosaurs(2) = "Microraptor"
  100.  
  101.        Console.WriteLine(vbLf & "Remove(""Microraptor"")")
  102.        dinosaurs.Remove("Microraptor")
  103.  
  104.        Console.WriteLine(vbLf & "RemoveAt(0)")
  105.        dinosaurs.RemoveAt(0)
  106.  
  107.        Display(dinosaurs)
  108.  
  109.    End Sub
  110.  
  111.    Private Shared Sub Display(ByVal cs As Collection(Of String))
  112.        Console.WriteLine()
  113.        For Each item As String In cs
  114.            Console.WriteLine(item)
  115.        Next item
  116.    End Sub
  117.  
  118.    Private Shared Sub ChangedHandler(ByVal source As Object, _
  119.        ByVal e As DinosaursChangedEventArgs)
  120.  
  121.        If e.ChangeType = ChangeType.Replaced Then
  122.            Console.WriteLine("{0} was replaced with {1}", _
  123.                e.ChangedItem, e.ReplacedWith)
  124.  
  125.        ElseIf e.ChangeType = ChangeType.Cleared Then
  126.            Console.WriteLine("The dinosaur list was cleared.")
  127.  
  128.        Else
  129.            Console.WriteLine("{0} was {1}.", _
  130.                e.ChangedItem, e.ChangeType)
  131.        End If
  132.    End Sub
  133.  
  134. End Class
  135.  
  136. ' This code example produces the following output:
  137. '
  138. 'Psitticosaurus was Added.
  139. 'Caudipteryx was Added.
  140. 'Compsognathus was Added.
  141. 'Muttaburrasaurus was Added.
  142. '
  143. 'Psitticosaurus
  144. 'Caudipteryx
  145. 'Compsognathus
  146. 'Muttaburrasaurus
  147. '
  148. 'IndexOf("Muttaburrasaurus"): 3
  149. '
  150. 'Contains("Caudipteryx"): True
  151. '
  152. 'Insert(2, "Nanotyrannus")
  153. 'Nanotyrannus was Added.
  154. '
  155. 'dinosaurs(2): Nanotyrannus
  156. '
  157. 'dinosaurs(2) = "Microraptor"
  158. 'Nanotyrannus was replaced with Microraptor
  159. '
  160. 'Remove("Microraptor")
  161. 'Microraptor was Removed.
  162. '
  163. 'RemoveAt(0)
  164. 'Psitticosaurus was Removed.
  165. '
  166. 'Caudipteryx
  167. 'Compsognathus
  168. 'Muttaburrasaurus
  169.  



Título: Re: Ayuda con una propiedad tipo lista en un custom control
Publicado por: <ИΘZIЭ(ŦB> en 22 Marzo 2011, 21:21 pm
Bueno, después de tanto revisar y probar noté que el problema con Remove solo se presenta en modo de diseño. Es decir, cuando agrego mi control a un formulario y accedo a la colección a través de la propiedad, y le quito items, pues no se ejecuta el Remove de la colacción; pero si pongo un botón en el formulario para remover un item, ejecuto la aplicación y oprimo el botón, ahí sí se ejecuta el bloque Remove. No sé por qué pero así ocurre. Lo extraño es que en modo diseño sí se ejecuta el bloque Add. ¿Alguna idea de por qué?