Título: Como crear un array de controles desde un módulo dentro de un control (Panel)
Publicado por: Lekim en 22 Septiembre 2015, 19:36 pm
Hola amigos Hasta ahora he estado usando Windows Forms, pero para conseguir un aspecto gráfico más bonito en mi aplicación he decidido usar WPF. El problema es que cambian algunos eventos y propiedades y otras cosas y tengo que ir investigando. Me ha pasado que ya tenía una apliación hecha en Windows Forms y he ido pasado el código a WPF pero resulta que concretamente esto no lo he sabido resolver. En Windows Forms creé un Panel y un array de controles con Labels. El panel se crea desde un módulo que he llamado (modCrearPanel). El módulo también tiene eventos y más cosas pero no viene a cuento. La cuestión es poder crear los Labels dentro de un control StackPanel en WPF. - Primero: Creo un Panel o StackPanel en el Windows Forms y en MainWindow en WPF - Segundo paso: EN WINDOWS FORMS (no es el código original, es una simplificación) Module Module1 Dim Etiqueta As New Label Dim lblEtiqueta(4) As Label Sub CrearPanel() Dim Y As Integer = 20 Dim X As Integer Form1.Panel1.BackColor = Color.DarkGray X = 10 'valor X inicial For I as Integer = 0 To 3 lblEtiqueta(I) = New Label lblEtiqueta(I).Width = 15 lblEtiqueta(I).Height = 15 lblEtiqueta(I).BackColor = Color.Gray lblEtiqueta(I).Location = New Point(X, Y) 'posición X e Y del cuadro Form1.Panel1.Controls.Add(lblEtiqueta(I)) 'Crea el label X = X + 20 Next End Sub End Module
CON WPF (NO FUNCIONA) Module Module1 Dim Etiqueta As New Label Dim lblEtiqueta(4) As Label Dim Main As MainWindow Public Sub CrearPanel() Dim Y As Integer = 10 Dim X As Integer Main.StackPanel1.Background = Brushes.DarkGray X = 10 For i As Integer = 0 To 3 lblEtiqueta(i) = New Label lblEtiqueta(i).Background = Brushes.Gray lblEtiqueta(i).Width = 15 lblEtiqueta(i).Height = 15 lblEtiqueta(i).Margin = New Thickness(0, X, Y, 0) X = X + 20 Main.StackPanel1.Children.Add(lblEtiqueta(i)) Next i Main.Show() End Sub End Module
Para crear el Penel se llama desde el Load o Loaded en WPF a CrearPanel. Con toda seguridad el problema está en la forma de poder hacer referencia al StackPanel1 que se encuentra en MainWindow. No se como se hace. Gracias por ayuda Encontré la forma :laugh: Module Module1 Dim Etiqueta As New Label Dim lblEtiqueta(4) As Label Private app As Application Private Main As MainWindow Public Sub CrearPanel() Dim Y As Integer = 10 Dim X As Integer app = System.Windows.Application.Current Main = CType(app.MainWindow, MainWindow) Main.StackPanel1.Background = Brushes.DarkGray X = 10 For i As Integer = 0 To 3 lblEtiqueta(i) = New Label lblEtiqueta(i).Background = Brushes.Gray lblEtiqueta(i).Width = 15 lblEtiqueta(i).Height = 15 lblEtiqueta(i).Margin = New Thickness(0, X, 0, Y) X = X + 20 Main.StackPanel1.Children.Add(lblEtiqueta(i)) 'Crea el label Next i End Sub End Module
Esto es lo que había que añadir al código para poder hacer referencia a objetos creados en MainWindow Private app As Application Private Main As MainWindow Public Sub CrearPanel() app = System.Windows.Application.Current Main = CType(app.MainWindow, MainWindow) Main.StackPanel1.Background = Brushes.DarkGray End Sub
Encontré la solución aquí: https://msdn.microsoft.com/es-es/library/vstudio/ms750944%28v=vs.100%29.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1 (https://msdn.microsoft.com/es-es/library/vstudio/ms750944%28v=vs.100%29.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1) Ahora que lo he conseguido hacer solo falta colocar correctamente los labels ya que en susitución a "Location" he usado "Margin" y no funciona igual. Veré a ver :-\ Saludos
Título: Re: Como crear un array de controles desde un módulo dentro de un control (Panel)
Publicado por: Eleкtro en 22 Septiembre 2015, 20:58 pm
Respecto al código que has mostrado para WindowsForms, yo evitaría el uso de un módulo en el cual supuestamente defines eventos y los disparas o pones en escucha algún event-handlers despreocupándote de su tiempo de vida, donde además declaras objetos (controles) que probablemente nunca liberarás maunálmente (hasta finalizar la app), pues yo lo haría más o menos así ...dentro de lo que cabe para este ejemplo en particular, en una Class que implementa la interfáz IDisposable: Public Class TestClass : Implements IDisposable Private ReadOnly lbl As Label Private ReadOnly lblArray(3) As Label Private ReadOnly pnl As Panel <DebuggerStepThrough> Public Sub New(ByVal pnl As Panel) Me.pnl = pnl Me.lbl = New Label For index As Integer = 0 To (Me.lblArray.Length - 1) Me.lblArray(index) = New Label Next index Me.CrearPanel() End Sub Private Sub New() End Sub Private Sub CrearPanel() Dim startPos As New Point(x:=10, y:=20) Dim margin As Integer = 20 Me.pnl.BackColor = Color.DarkGray For Each lbl As Label In Me.lblArray With lbl .Width = 15 .Height = 15 .BackColor = Color.Gray .Location = startPos 'posición X e Y del cuadro startPos.X += margin End With Next lbl If Not Me.pnl.InvokeRequired Then Me.pnl.Controls.AddRange(Me.lblArray) Else Me.pnl.Invoke(Sub() Me.pnl.Controls.AddRange(Me.lblArray)) End If End Sub #Region "IDisposable Support" ' To detect redundant calls when disposing. Private isDisposed As Boolean = False ''' <summary> ''' Releases all the resources used by this instance. ''' </summary> Public Sub Dispose() Implements IDisposable.Dispose Me.Dispose(isDisposing:=True) GC.SuppressFinalize(obj:=Me) End Sub Protected Sub Dispose(ByVal isDisposing As Boolean) If Not Me.isDisposed Then If isDisposing Then ' Dispose managed objects here... If Me.lbl IsNot Nothing Then Me.lbl.Dispose() End If For Each lbl As Label In Me.lblArray If lbl IsNot Nothing Then lbl.Dispose() End If Next lbl End If End If Me.isDisposed = True End Sub #End Region End Class
Modo de empleo: Dim cosa As New TestClass(Me.Panel1) ' cosa.Dispose()
Sobre WPF, asumiré que el control que has elegido cómo equivalente de un panel es un Canvas, en caso contrario hazlo (es lo recomendable por la MSDN). La respuesta corta es que debes asignar el margen del control con el uso de la propiedad Margin: Label.Margin = New Thickness(Point.X, Point.Y, 0, 0)
También puedes utilizar las funciones Canvas.SetLeft y Canvas.SetTop para asignar el margen de un control hijo: Canvas.Children.Add(Label) Canvas.SetLeft(label, Point.X) Canvas.SetTop(label, Point.Y)
La respuesta larga es que, si te sientes más agusto con la familiaridad de la tecnología WindowsForms, entonces podrías heredar un label para definir la propiedad personalizada Location y usarla cómo la solias usar antes: Public Class CustomLabel : Inherits Label Public Property Location() As Point Get Return New Point(MyBase.Margin.Left, MyBase.Margin.Top) End Get Set(ByVal value As Point) ' La lógica del método "Set" se podría mejorar para que realmente se pueda considerar un "Location". MyBase.Margin = New Thickness(value.X, value.Y, 0, 0) End Set End Property End Class
Y este código sería el equivalente para WPF de la class de WinForms que mostré arriba, donde aquí como puedes ver no implemento la interfáz IDisposable, ya que a diferencia de WinForms, la mayoría de controles realmente no tienen ningún recurso que liberar. Public NotInheritable Class TestClass Private ReadOnly lbl As Label Private ReadOnly lblArray(3) As Label Private ReadOnly pnl As Canvas <DebuggerStepThrough> Public Sub New(ByVal pnl As Canvas) Me.pnl = pnl Me.lbl = New Label For index As Integer = 0 To (Me.lblArray.Length - 1) Me.lblArray(index) = New Label Next index Me.CrearPanel() End Sub Private Sub New() End Sub Private Sub CrearPanel() Dim startPos As New Point(x:=10, y:=20) Dim margin As Integer = 20 Me.pnl.Background = Brushes.Gray For Each lbl As Label In Me.lblArray With lbl .Width = 15 .Height = 15 .Background = Brushes.Red .Margin = New Thickness(startPos.X, startPos.Y, 0, 0) startPos.X += margin End With Me.pnl.Children.Add(lbl) Next lbl End Sub End Class
Modo de empleo: Dim cosa As New TestClass(Me.Canvas1)
Saludos
Título: Re: Como crear un array de controles desde un módulo dentro de un control (Panel)
Publicado por: Lekim en 23 Septiembre 2015, 15:54 pm
Gracias muy buena respuesta, me has resuelto todas las dudas.;-)
Y lo del canvas es lo que buscaba, creía que el equivalente en WPF era el stackpanel :P
Título: Re: Como crear un array de controles desde un módulo dentro de un control (Panel)
Publicado por: Eleкtro en 23 Septiembre 2015, 16:31 pm
Y lo del canvas es lo que buscaba, creía que el equivalente en WPF era el stackpanel :P Esto te podría servir de ayuda para futuras dudas respecto a otros controles... ➢ Windows Forms Controls and Equivalent WPF Controls - MSDN (https://msdn.microsoft.com/en-us/library/vstudio/ms750559%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396) Saludos!
Título: Re: Como crear un array de controles desde un módulo dentro de un control (Panel)
Publicado por: Lekim en 23 Septiembre 2015, 17:41 pm
Ok, gracias Elektro Por curiosidad he probado de hacer algo parecido con el código que expuse al principio. A ver que te parece ::) Module Module1 Dim lblEtiqueta(4) As Label Sub CrearPanel(ByVal pnl As Object, ByVal Disponible As Boolean) Dim Starlbl As New Point(x:=10, y:=20) pnl.backcolor = Color.DarkGray If Disponible Then For I As Integer = 0 To 3 lblEtiqueta(I) = New Label lblEtiqueta(I).Width = 15 lblEtiqueta(I).Height = 15 lblEtiqueta(I).BackColor = Color.Gray lblEtiqueta(I).Location = Starlbl 'posición X e Y del cuadro pnl.Controls.Add(lblEtiqueta(I)) 'Crea el label Starlbl.X += 20 Next Else Try For Index As Integer = 0 To 3 lblEtiqueta(Index).Dispose() Next Index Catch ex As Exception End Try End If End Sub End Module
Para llamar uso: (para mostrar los Labels) CrearPanel(Panel1, True)
(para quitar los labels) CrearPanel(Panel1, False)
|