Enero 17, 2018, 08:41:55 pm

Autor Tema: Equivalencias entre las clases de WPF y las de .NET  (Leído 8169 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Rakzo-Fimbres

  • Yo vivo en CPH
  • ***
  • Mensajes: 645
  • Sexo: Masculino
  • Q.E.P.D. Misha :)
    • Ver Perfil
Equivalencias entre las clases de WPF y las de .NET
« en: Abril 11, 2009, 09:25:03 pm »
Bien, hoy vamos a ver todas las diferencias obtenidas entre programar en un WPF que en un WindowsForms. Quizás ya lo hayas visto antes, pero de igual forma a uno le sirve como repaso.

Cuando quieres usar en una aplicación de WinFX algunas cosas a las que estás acostumbrado en .NET Framework 2.0, puedes encontrarte con algunas sorpresas.

Seguramente las podrás solucionar fácilmente, pero... para que te sea más cómodo, aquí te explico algunas.
En otras actualizaciones de este artículo (o de uno nuevo que continúe este) te explicaré más cosas.

1- No existe la propiedad Text de los controles
Debido a como funcionan los controles de WPF, la propiedad Text a la que estamos acostumbrados ya no está, ahora se puede usar la propiedad Content, que aunque es mucho más "potente" que el mero hecho de mostrar texto, al menos será la que usemos para asignar los textos a mostrar en algunos controles.
Código: You are not allowed to view links. Register or Login
LabelStatus.Content = "¡Hola, Mundo!"
2- La ventana principal tampoco tiene Text
Algo que me gustaba de la versión de .NET es que se consiguió eliminar la "multipliciidad" de propiedades que servían para mostrar un texto, ahora con WPF volvemos "pa trás" y... en fin... Bueno, decirte que la ventana principal (siempre que sea una ventana basada en la clase Window), el texto a mostrar en la barra del título, se asigna por medio de la propiedad Title:
Código: You are not allowed to view links. Register or Login
Me.Title = "El título de la ventana"
3- No existe la propiedad Checked (ahora es un evento)
Ahora, la propiedad Checked de los controles que aceptan esa propiedad se llama IsChecked.
Por otra parte, Checked es un evento que se produce cuando el control en cuestión se "chekea".
Código: You are not allowed to view links. Register or Login
If chkMinimizar.IsChecked Then
4- No existe el evento CheckedChanged
Ese evento es el que normalmente solemos usar para comprobar si se ha cambiado el estado de chequeado o no de un control que soporta ese estado de si "IsChecked" o no. Bueno, podemos usar tanto CheckedChanged como CheckStateChanged, cualquiera de los dos nos avisa de que ha cambiado el estado "chequeado" del control.

Pero en los controles de WinFX ahora hay dos eventos para averiguar ese cambio, por un lado tenemos el evento Checked para indicar que el control está "marcado" y por otro tenemos el evento UnChecked para indicarnos que no está marcado. Pero debido a que tanto uno como el otro usan los mismos parámetros en el método del evento, podemos unificarlos los dos y seguir usando el mismo código que teníamos, por ejemplo, en las versiones anteriores a .NET Framework 3.0 (WinFX) el código sería algo así:
Código: You are not allowed to view links. Register or Login
Private Sub chkMezclar_CheckedChanged( _
            ByVal sender As Object, _
            ByVal e As EventArgs) Handles chkMezclar.CheckedChanged
    If Me.inicializando Then Exit Sub
    '
    Me.mezclarCanciones = Me.chkMezclar.Checked
    If Me.chkMezclar.Checked Then
        mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "1")
    Else
        mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "0")
    End If
End Sub

En una aplicación para WPF sería de esta otra forma: (usando los dos eventos)
Código: You are not allowed to view links. Register or Login
Private Sub chkMezclar_Checked(ByVal sender As Object, _
                               ByVal e As RoutedEventArgs) _
                               Handles chkMezclar.Checked
    If Me.inicializando Then Exit Sub

    Me.mezclarCanciones = True
    mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "1")
End Sub

Private Sub chkMezclar_Unchecked(ByVal sender As Object, _
                                 ByVal e As RoutedEventArgs) _
                                 Handles chkMezclar.Unchecked
    If Me.inicializando Then Exit Sub

    Me.mezclarCanciones = False
    mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "0")
End Sub

Que podemos "unificar" en un solo método y usarlo tal como hacemos hasta ahora:
Código: You are not allowed to view links. Register or Login
Private Sub chkMezclar_CheckedChanged(ByVal sender As Object, _
                                      ByVal e As RoutedEventArgs) _
                                      Handles chkMezclar.Checked, chkMezclar.Checked
    If Me.inicializando Then Exit Sub

    Me.mezclarCanciones = Me.chkMezclar.IsChecked.Value

    If Me.chkMezclar.IsChecked Then
        mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "1")
    Else
        mINI.IniWrite(sFicIni, "General", "Mezclar canciones", "0")
    End If
End Sub

5- Muchas de los tipos habituales de Windows.Forms están definidos en Windows
Pues eso... que muchos de eventos habituales, clases, enumeraciones, etc., que usamos en nuestros proyectos par aplicaciones de escritorio de .NET 2.0 y que suelen estar definidos en el espacio de nombres System.Windows.Forms, ahora están definidos en System.Windows.

Debes tener en cuenta que aunque el espacio "raíz" sea el mismo (System.Windows), en realidad son librerías distintas.

Si quieres usar las cosas "viejas" de System.Windows.Forms, debes agregar una referencia a la librería System.Windows.Forms.dll.

Pero NO TE RECOMIENDO que agregues una importación al espacio de nombres System.Windows.Forms, ya que si lo haces, pues tendrás "inconsistencias" entre esas clases o tipos que se llaman igual en los dos espacios de nombres.

6- La clase MessageBox y las enumeraciones de esa clase
Un caso concreto de las clases que están definidas en los dos sitios es la "habitual" MessageBox. La clase en sí no da problemas, pero si los parámetros.

Por ejemplo, este código que funciona bien en una aplicación de .NET 2.0 (o anterior), fallará en una aplicación para WPF:
Código: You are not allowed to view links. Register or Login
MessageBox.Show("ERROR: " & ex.Message, _
            "Error al tocar", _
            MessageBoxButtons.OK,
            MessageBoxIcon.Exclamation)

Tendrás que usar el siguiente código:
Código: You are not allowed to view links. Register or Login
MessageBox.Show("ERROR: " & ex.Message, _
                "Error al tocar", _
                MessageBoxButton.OK, _
                MessageBoxImage.Exclamation)

A lo mejor piensas que son iguales. Pero no te fíes... esto no es uno de esos juegos de buscar las diferencias.

Esto es algo "común" en las clases de WPF, el que se inventó los nombres seguro que estaba "fumao" o recibió una inspiración divina... en serio, seguramente pensó que es más "guay" (cool, molón, chido, etc.)  usar nuevos nombres "más adecuados", ya que si te fijas bien, los tipos de botones a mostrar en las aplicaciones "actuales" están definidos en la enumeración MessageBoxButtons, mientras que en WPF están en MessageBoxButton, es decir, lo mismo, pero sin la "recomendada" ese del plural al final.
Lo mismo ocurre con la enumeración de los iconos a mostrar, en las aplicaciones de Windows.Forms se usa MessageBoxIcon y en WPF es MessageBoxImage.

Y como esto... muchos casos parecidos, por ejemplo... (sigue leyendo).

7- Cambios en Drag & Drop
En este caso, hay varios cambios... de nombres, no de forma de usarlo.

Por ejemplo, hay que tener en cuenta que cuando definimos el método para interceptar los eventos de arrastrar y soltar (Drag & Drop), en nuestras aplicaciones de .NET "normal" el código será más o menos como este:
Código: You are not allowed to view links. Register or Login
Private Sub fgsPlayMCIAPI_DragDrop(ByVal sender As Object, _
                                   ByVal e As System.Windows.Forms.DragEventArgs) _
                                   Handles MyBase.DragDrop
    addDrop2List(e.Data)
End Sub

Private Sub fgsPlayMCIAPI_DragOver(ByVal sender As Object, _
                                   ByVal e As System.Windows.Forms.DragEventArgs) _
                                   Handles MyBase.DragOver
    e.Effect = DragDropEffects.Copy
End Sub

Y en una aplicación de WPF, eso mismo se haría así:
Código: You are not allowed to view links. Register or Login
Private Sub fgsPlayMCIAPI_DragDrop(ByVal sender As Object, _
                                   ByVal e As DragEventArgs) _
                                   Handles MyBase.Drop
    addDrop2List(e.Data)
End Sub

Private Sub fgsPlayMCIAPI_DragOver(ByVal sender As Object, _
                                   ByVal e As DragEventArgs) _
                                   Handles MyBase.DragOver
    e.Effects = DragDropEffects.Copy
End Sub

Busca las diferencias (que son las que te he marcado en el primer código).

En el caso del parámetro, volvemos a lo que te he comentado en el punto 5.
Se llaman igual, pero están definidos en espacios de nombres distintos.

El segundo cambio es el nombre de la propiedad a la que hay que asignar el "efecto", y es que ahora está en plural, mientras que antes estaba en singular... sin más comentarios de los que ya hice antes.

El tercero, y más importante, es el cambio del nombre del evento que "acepta" la operación de soltar, hasta ahora se llamaba DragDrop, pero en WinFX se llama Drop. ¡Que lo sepas!

8- Cambios en las teclas pulsadas en los eventos KeyDown y KeyUp
Otro follón con los nombres de las propiedades y demás... en este caso, si desde el evento KeyDown o KeyUp quieres averiguar que la tecla pulsada es una en concreto, pues... debes usar otros nombres.

Por ejemplo, este sería el código para .NET "normal":
Código: You are not allowed to view links. Register or Login
Private Sub ListView1_KeyDown(ByVal sender As Object, _
            ByVal e As System.Windows.Forms.KeyEventArgs) _
            Handles lvCanciones.KeyDown
    ' Si se pulsa la tecla DEL, borrar el seleccionado
    If e.KeyCode = System.Windows.Forms.Keys.Delete Then
        If lvCanciones.SelectedItems.Count = 0 Then Return
        ' Borrar
        lvCanciones.Items.RemoveAt(lvCanciones.SelectedItems(0).Index)
        guardarListaActual()
    End If
End Sub

No te resalto las diferencias para que mejores tu capacidad visual, je, je, (esto como lo de "Brain trainer ese").
Este sería el código equivalente para WPF:
Código: You are not allowed to view links. Register or Login
Private Sub ListView1_KeyDown(ByVal sender As Object, _
                              ByVal e As KeyEventArgs) _
                              Handles lvCanciones.KeyDown
    ' Si se pulsa la tecla DEL, borrar el seleccionado
    If e.Key = Key.Delete Then
        If lvCanciones.SelectedItems.Count = 0 Then Return
        ' Borrar
        lvCanciones.Items.RemoveAt(lvCanciones.SelectedItems(0).Index)
        guardarListaActual()
    End If
End Sub

Aparte de que en lugar de la propiedad KeyCode hay que usar Key y de que en lugar de comprobar si es un valor de la enumeración Keys ahora esa enumeración se llama Key, debemos recordar que los espacios de nombres usados en WPF son distintos a los de las aplicaciones de Windows.Forms de .NET 2.0, sí, ya sé que te lo he dicho varias veces, pero...

Además, me he dado cuenta de que ese código solo funcionará si Option Strict está desconectado. Ya que... mira el siguiente punto.

9- La colección SelectedItems de un ListView es de tipo Object (IList)
En este caso, voy a hablar de la colección SelectedItems del control ListView. Pero estos cambios también afectan a los controles ComboBox y ListBox, aunque menos.

En .NET 2.0, la colección SelectedItems del ListView devuelve una colección de tipo ListView.SelectedListViewItemCollection (definida en System.Windows.Forms). Esa colección devuelve valores del tipo ListViewItem, por tanto, podemos acceder a ciertos valores o propiedades del elemento seleccionado que estamos "observando".

Pero en WPF no es lo mismo, ya que esa colección es de tipo IList, por tanto, devuelve valores de tipo Object.

 ¿Por qué? Por lo que ya te comenté antes, porque ahora en WPF el contenido de los controles pueden ser... ¡cualquier cosa! Es decir, un control ListView puede tener más cosas que "simples" objetos del tipo ListViewItem, así que... hay que tener en cuenta esto.

En el código que te mostré antes, para saber el índice del primer elemento que estaba seleccionado usaba este código:
Código: You are not allowed to view links. Register or Login
lvCanciones.SelectedItems(0).Index
Para ese caso concreto en el que quiero averiguar el índice del primer elemento seleccionado, lo puedes hacer así:
Código: You are not allowed to view links. Register or Login
lvCanciones.SelectedIndex
Y si lo que quieres es recuperar el texto del elemento seleccionado... mira el punto 10:

10- El elemento seleccionado de un ListView es de tipo Object
Siguiendo con el tema del punto anterior, decirte que el valor devuelto por la propiedad SelectedItem de la clase ListView ahora en WPF es de tipo Object (por aquello de que puede contener cualquier cosa, bla, bla, bla).

Pero si sabes que lo que contiene es simplemente texto, y el código que usabas hasta ahora es algo como esto:
Código: You are not allowed to view links. Register or Login
toolTip1.SetToolTip(lvCanciones, _
                    "Seleccionado: " & lvCanciones.SelectedItems(0).Text)

Aquí tienes que "ver" dos cosas, una es que el texto se accede con SelectedItems(0).Text, es decir, el texto del primer elemento que está seleccionado se asigna al "tool tip" relacionado con el ListView.

En WPF yo lo he hecho así:
Código: You are not allowed to view links. Register or Login
lvCanciones.ToolTip = "Seleccionado: " & lvCanciones.SelectedItem.ToString

Es decir, ahora SelectedItem nos indica el elemento que está seleccionado en el control ListView, y como resulta que ese "objeto" devuelto es de tipo Object, y "yo sé" que en realidad es una cadena de texto, pues simplemente lo convierto en texto usando el método ToString.

La segunda cosa es que en WPF todos los controles (creo que todos) tienen la propiedad Tooltip, por tanto, a esa propiedad es a la que asigno el "tool tip" que quiero mostrar.

11- El evento SelectedIndexChanged ahora es SelectionChanged
Al menos en el control ListView (en los otros controles no lo he comprobado, pero al menos en el control ComboBox también se llama así).

La cosa es que el "efecto" conseguido es el mismo... saber si se ha seleccionado otro elemento distinto al que antes estaba seleccionado, pero... para que sepas que ahora se llama de otra forma.

12- Los eventos de inicio y cierre de la ventana principal
Seguramente de estos dos eventos, en todas tus aplicaciones usas el que "inicia" el formulario principal, que en las aplicaciones "normales" es el evento producido por el evento Load.

En WPF ese evento ya no existe.

No te asustes, je, je, que no existe con ese nombre, ya que ahora se llama Loaded, que seguramente le habrán cambiado el nombre para que quede claro que el formulario (perdón, la ventana) ya está cargado.

El evento de cierre de los formularios de nuestras aplicaciones clásicas (de .NET 2.0) utilizan el evento FormClosing para avisar de que el formulario se está cerrando. En ese evento se avisa de varias cosas que podemos usar para saber más sobre cómo se cierra.

En WPF se llama como "antes", es decir, es Closing y el tipo de parámetro que recibe es del mismo tipo: System.ComponentModel.CancelEventArgs. Osea... casi un paso atrás, je, je.

13- El tipo de IsChecked es Boolean? (Nullable(Of Boolean))
Pues eso, como ya te dije, que esa propiedad es la que sirve para saber si un control está "checado" o no, y como el tipo de datos de esa propiedad es Nullable(Of Boolean) (Nullable<bool> en C#) para obtener el valor y usarlo para una asignación, tendremos que usar IsChecked.Value.

14-El tipo devuelto por los cuadros de diálogos basados en Microsoft.Win32
En las aplicaciones de WPF, si queremos mostrar los cuadros de diálogo de abrir o guardar (OpenFileDialog y SaveFileDialog), debemos tener en cuenta que están definidos en el espacio de nombres Microsoft.Win32 y que a diferencia de los que están definidos en System.Windows.Forms (los que solemos usar en las aplicaciones de .NET normal), el método ShowDialog devuelve True o False; en cuyo caso, False es que se ha cancelado.

15- El evento para saber si se minimiza la ventana
Cuando la ventana se minimiza, etc., se dispara el evento StateChanged (antes era Resize).
Aunque antes de que se dispare ese evento, se dispara también el evento LocationChanged.

16- El evento cuando se mueve el formulario
En las ventanas (objetos de tipo Window) en las aplicaciones WPF no existe el evento Move que es el que (al menos yo) solemos usar para saber si se ha cambiado la posición de una ventana. En WPF hay que usar el evento LocationChanged que por cierto, en los formularios de Windows.Forms también existe.

17- Asegurarnos de que un elemento de un ListView sea visible
Cuando "movemos" el elemento seleccionado en un ListView, para asegurarnos de que ese elemento se muestre (porque esté más arriba o más abajo de los elementos que se muestran), en las aplicaciones Windows.Forms tenemos que usar EnsureVisible, pero en las aplicaciones WPF debemos usar ScrollIntoView.

En ambos casos debemos asignar el índice del elemento que queremos que se muestre, valor que debemos pasar como argumento a esos métodos.

18- Quitar la selección a los elementos seleccionados de un ListView
En el ListView de Windows.Forms no se si existe esto... pero en el control ListView de WPF puedes usar SelectedItems.Clear().

19- Para poner una ventana encima del resto
En WPF tendrás que usar Me.Topmost = True en lugar de Me.BringToFront()

20- Los valores de Left, Top, Height y Width son Double en lugar de Integer
Pues eso... parece una tontería, pero... en algunos casos te puede dar "quebraderos" de cabeza, sobre todo si esos valores aún no están asignados (por ejemplo mientras se carga la ventana principal), ya que el valor devuelto es... bueno... cualquier cosa menos un número, je, je... experiméntalo por tu cuenta y verás a que me refiero.

Pero no te asustes, solo te dará "problemas reales" si pretendes convertirlo a cadena y aún no tiene un valor válido.

21-AddressOf no "encaja" bien en todos los eventos enrutados
Pues eso... que si pretendes asignar el método de un evento "enrutado" (o ruteado que dicen otros), en lugar de usar AddressOf método, tendrás que usar New RoutedEventHandler(AddressOf método).

22- Consejo de inicialización de la ventana principal
Normalmente hacemos todo el proceso de inicialización en el evento Load del formulario (o Loaded de la clase Window de WPF), pero si es mucho lo que tienes que hacer, pues... verás que parece una "chapuza", por ejemplo, si mueves el formulario de sitio o lo cambias de tamaño, (para que use los valores de una ejecución anterior, por ejemplo). En las pruebas que yo he hecho, si ese código de inicialización lo pongo en el constructor (después de InitializeComponent), el resultado es más "fresco".

Aunque esto mismo en las aplicaciones de Windows.Forms no tienen el mismo efecto, de hecho en las aplicaciones "normales" es posible que el formulario se quede detrás del resto.

23- Sobre cómo cambiar el estado de visibilidad
En las aplicaciones de Windows.Forms, usábamos Visible para saber si un control estaba "a la vista" o si queríamos cambiar el estado de visibilidad, pero en WPF esto ha cambiado.

En WPF, para saber si "algo" está visible o no, debemos usar la propiedad IsVisible, que al ser de solo lectura, solo nos servirá para saber si está o no visible. Si queremos cambiar "la visibilidad" de algún control, debemos usar la propiedad Visibility que acepta los tres valores de la enumeración del mismo nombre, y que pueden ser:

Visible, se muestra.
Hidden, se oculta, pero se le reserva el espacio que ocupa.
Collapsed, se oculta y no se le reserva espacio.

Eso de "reservar el espacio", bueno... debes probarlo, en este ejemplo de la documentación de Visual Studio 2008 Beta 2 puedes ver el efecto (está en el ejemplo de la enumeración Visibility):
ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_presentationcore/html/40d66826-6e19-d0dd-b3b6-92a880399301.htm

En cualquier caso... el asignar un valor a la propiedad Visibility no te asegura que "ocurra"... o eso dice la documentación, de hecho, en los "formularios" actúa como le da la gana... en fin...

24- Acceder a un control desde un evento de un timer
Para terminar este repaso de hoy a las equivalencias entre las aplicaciones .NET "normales" y las de WPF, déjame decirte que es sobre cómo acceder a un control o cualquier otra cosa que se esté ejecutando en otro hilo desde un hilo diferente, por ejemplo, desde el evento Elapsed de un temporizador.

En Visual Basic el código para acceder al método "miMétodo" sería este:
Código: You are not allowed to view links. Register or Login
Me.Dispatcher.Invoke(DispatcherPriority.Normal, New InvocarCallback(AddressOf MiMétodo))
InvocarCallBack es un delegado que tendrá la misma firma que el método al que queremos llamar, en caso de que no reciba ningún parámetro lo declararemos así:
Código: You are not allowed to view links. Register or Login
Public Delegate Sub InvocarCallback()
Espero que te sea de utilidad.
Fuente: elGuille.
« Última modificación: Abril 11, 2009, 09:26:29 pm por Rakzo-Fimbres »
You are not allowed to view links. Register or Login


question
Con Puntero de Clases Entre Clases

Iniciado por TetraBytes

2 Respuestas
2492 Vistas
Último mensaje Mayo 07, 2009, 02:49:35 pm
por TetraBytes
smiley
Equivalencias del tiempo en internet…

Iniciado por proton6

14 Respuestas
1752 Vistas
Último mensaje ſeptiembre 03, 2008, 01:24:55 pm
por proton6
xx
Equivalencias de programas de Windows en Linux

Iniciado por Axus

7 Respuestas
2147 Vistas
Último mensaje Agosto 22, 2008, 02:08:53 pm
por rakamajaka
xx
Tabla de equivalencias Windows-Linux en castellano

Iniciado por vart001

0 Respuestas
1147 Vistas
Último mensaje Junio 02, 2005, 05:24:15 pm
por vart001
xx
clases en C++

Iniciado por diablokira

4 Respuestas
1273 Vistas
Último mensaje Enero 27, 2011, 09:55:12 am
por diablokira
xx
Clases en CSS

Iniciado por eriik

3 Respuestas
2155 Vistas
Último mensaje Marzo 11, 2008, 01:38:00 am
por eriik
xx
CLASES DE VIRUS

Iniciado por wanm28

1 Respuestas
1721 Vistas
Último mensaje Agosto 01, 2007, 12:08:58 pm
por Pancho111
xx
[DUDA]Clases

Iniciado por vVegeta

3 Respuestas
1879 Vistas
Último mensaje Mayo 27, 2008, 03:07:00 am
por kamui23
question
Clases que se necesitan

Iniciado por 60NZ4L3Z

4 Respuestas
1620 Vistas
Último mensaje Mayo 17, 2011, 01:53:57 pm
por WaesWaes
question
ayuda con clases ado.net

Iniciado por Skynet2

1 Respuestas
1803 Vistas
Último mensaje Junio 24, 2009, 06:43:56 pm
por ranefi