Colabora
 

Interfaze INotifyPropertyChanged

[Implementando interfaces .NET]

 

Fecha: 04/Dic/2008 (02-12-08)
Autor: Joaquin Medina Serrano - joaquin@medina.name

 


Sumario

La interfaz INotifyPropertyChanged proporciona un mecanismo unificado para definir en un único evento las propiedades Changed que queramos definir en nuestros objetos.

 


↑↑↑

Introducción

Cuando se crea un objeto, o un control, o un componente, es habitual la implementación de un sistema que notifique al cliente (que usa el control) que se ha producido un cambio en alguna de sus propiedades. Normalmente se realiza escribiendo eventos del tipo PropiedadChanged. Esto da lugar a que un componente pueda contar con una lista bastante extensa de eventos, potencialmente tantos como propiedades puedan ser modificadas, que tienen siempre la misma finalidad: notificar que el contenido de una cierta propiedad ha cambiado.

La interfaz [System.ComponentModel.INotifyPropertyChanged], introducida en la versión 2.0 de la plataforma, proporciona un mecanismo para reunir en un unico evento todos los eventos 'changed' de nuestro objeto


↑↑↑

Clase con el ejemplo

Public Class Colega
    Implements System.ComponentModel.INotifyPropertyChanged


    Private mNombre As String
    Private mApellidos As String
    Private mTelefono As String


    Public Event PropertyChanged( _
           ByVal sender As Object, _
           ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
           Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged


    Public Property Nombre() As String
        Get
            Return mNombre
        End Get
        Set(ByVal value As String)
            If mNombre <> value Then
                mNombre = value
                RaiseEvent PropertyChanged( _
                Me, New System.ComponentModel.PropertyChangedEventArgs("Nombre"))
            End If
        End Set
    End Property

    Public Property Apellidos() As String
        Get
            Return mApellidos
        End Get
        Set(ByVal value As String)
            If mApellidos <> value Then
                mApellidos = value

                Dim nombrePropiedad As String
                nombrePropiedad = System.Reflection.MethodBase.GetCurrentMethod.Name
                RaiseEvent PropertyChanged( _
                Me, New System.ComponentModel.PropertyChangedEventArgs(nombrePropiedad))
            End If
        End Set
    End Property


 
End Class

↑↑↑

Implementando la Interfaz


↑↑↑

Paso Uno – Definir la interfaz

Public Class Colega
    Implements System.ComponentModel.INotifyPropertyChanged

↑↑↑

Paso Dos - Implementar la función de la interfaz

La interfaz INotifyPropertyChanged, cuenta como único miembro con el evento PropertyChanged, definido de la siguiente manera:

Public Event PropertyChanged( _
       ByVal sender As Object, _
       ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
       Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Aquí lo tienes más sencillo quitando todos los calificadores

Public Event PropertyChanged( _
           ByVal sender As Object, _
           ByVal e As.PropertyChangedEventArgs) _
           Implements INotifyPropertyChanged.PropertyChanged

Los parámetros de la definición deben contener la siguiente información:

  • sender: Referencia al componente (al objeto) que genera el evento.
  • e: Un objeto PropertyChangedEventArgs que contendrá el nombre de la propiedad que ha cambiado.

↑↑↑

Paso Tres - Disparar el Evento

Cuando haga falta comunicar la modificación de una propiedad, se utilizará la instrucción RaiseEvent para generar este evento

Public Property Nombre() As String
    Get
        Return mNombre
    End Get
    Set(ByVal value As String)
        If mNombre <> value Then
            mNombre = value
            RaiseEvent PropertyChanged( _
                       Me, New PropertyChangedEventArgs("Nombre"))
        End If
    End Set
End Property

Tambien podemos utilizar la reflexión para obtener el nombre del método o la propiedad, pero en este caso hay que tener en cuenta que una propiedad (por ejemplo Apellidos) tiene dos nombres, el correspondiente al apartado Set (que será set_Apellidos) y el correspondiente al apartado Get (que será get_Apellidos). Si desconoces este pequeño detalle, puedes tener errores tontos al identificar los nombres de la propiedad que ha "changed"

Public Property Apellidos() As String
    Get
        Return mApellidos
    End Get
    Set(ByVal value As String)
        If mApellidos <> value Then
            mApellidos = value
            Dim nombrePropiedad As String
            nombrePropiedad = System.Reflection.MethodBase.GetCurrentMethod.Name 
            ' ¡¡¡ ATENCION !!!
            ' La variable {nombrePropiedad} toma el valor {"set_Apellidos"}
            RaiseEvent PropertyChanged( _
                       Me, New PropertyChangedEventArgs(nombrePropiedad))
        End If
    End Set
End Property

↑↑↑

Paso Cuatro – Interceptar el evento

Solo por si acaso, la clase cliente tiene que instanciar un objeto (a nivel de clase) con la palabra clave [WithEvents] para poder interceptar los eventos de la clase

Dim WithEvents objColega As New Colega

Y a continuación, en la clase cliente, solo tenemos que interceptar el evento y tratarlo de la forma mas adecuada

Private Sub objColega_PropertyChanged( _
         ByVal sender As Object, _
         ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
         Handles objColega.PropertyChanged

     Me.TextBox1.Text = "Propiedad que cambia " & e.PropertyName
 End Sub
 

↑↑↑

A modo de resumen

Este sistema de notificación deberá implementarse en las clases (componentes, etc.) que acceden a datos y que pueden ser vinculados a un control (Data Binding) para mostrar su contenido.


↑↑↑

Más información:


↑↑↑

Referencias Bibliográficas

Un Buen libro

  • Programación Visual Basic 2008
    Francisco Charte Ojeda
    ISBN 978-84-415-2477-4

↑↑↑

Direcciones Web Interesantes

 


Espacios de nombres usados en el código de este artículo:

System.ComponentModel

 



Compromiso del autor del artículo con el sitio del Guille:

Lo comentado en este artículo está probado (y funciona) con la siguiente configuración:

El autor se compromete personalmente de que lo expuesto en este artículo es cierto y lo ha comprobado usando la configuración indicada anteriormente.

En cualquier caso, el Guille no se responsabiliza del contenido de este artículo.

Si encuentras alguna errata o fallo en algún link (enlace), por favor comunícalo usando este link:

Gracias.


Código de ejemplo (comprimido):

 

Este artículo no tiene ningún código de ejemplo

 


Ir al índice principal de el Guille