2011-11-03 17 views
12

Sé que MVVM usa mucho INotifyPropertyChanged, pero nunca he visto ningún uso de INotifyPropertyChanging. ¿Alguna razón por qué?¿Por qué nadie utiliza INotifyPropertyChanging?

Si quisiera usar esto, ¿cuál sería una buena manera de integrar esto en mi MVVM Framework? Sé que se supone que no debes usar MessageBox en tu ViewModel porque entonces no puedes probarlo en una unidad. Entonces, ¿cómo se puede lanzar una alerta, y luego continuar con el PropertyChange si corresponde?

+1

¿Qué es lo que quiere lograr aquí? ¿Cuál es el caso de uso para saber cuándo una propiedad está * sobre * cambiar? – ChrisF

+0

Para verificar al usuario "¿Estás seguro?" para ciertos cambios ... Queremos asegurarnos de que los administradores quieren cambiar el nombre de usuario/inicio de sesión de un usuario y no actualizaron accidentalmente el campo. – michael

Respuesta

11

Algo a tener en cuenta acerca de INotifyPropertyChanging es que no puede detener el cambio de ocurriendo. Esto simplemente le permite registrar que se produjo el cambio.

Lo uso en un marco de trabajo mío para el seguimiento de cambios, pero no es un método apropiado para detener cambios.

Se podría ampliar su ViewModelBase con un par interfaz personalizada/evento:

delegate void AcceptPendingChangeHandler(
    object sender, 
    AcceptPendingChangeEventArgs e); 

interface IAcceptPendingChange 
{ 
    AcceptPendingChangeHandler PendingChange; 
} 

class AcceptPendingChangeEventArgs : EventArgs 
{ 
    public string PropertyName { get; private set; } 
    public object NewValue { get; private set; } 
    public bool CancelPendingChange { get; set; } 
    // flesh this puppy out 
} 

class ViewModelBase : IAcceptPendingChange, ... 
{ 
    protected virtual bool RaiseAcceptPendingChange(
     string propertyName, 
     object newValue) 
    { 
     var e = new AcceptPendingChangeEventArgs(propertyName, newValue) 
     var handler = this.PendingChange; 
     if (null != handler) 
     { 
      handler(this, e); 
     } 

     return !e.CancelPendingChange; 
    } 
} 

En este punto, que había necesidad de añadir que por convención a sus modelos de vista:

class SomeViewModel : ViewModelBase 
{ 
    public string Foo 
    { 
     get { return this.foo; } 
     set 
     { 
      if (this.RaiseAcceptPendingChange("Foo", value)) 
      { 
       this.RaiseNotifyPropertyChanging("Foo"); 
       this.foo = value; 
       this.RaiseNotifyPropretyChanged("Foo"); 
      } 
     } 
    } 
} 
1

Para responder a la segunda pregunta, siempre puede usar el patrón de Inyección de dependencias para hacer que su máquina virtual dependa de una interfaz (¿INtifier?) Y pasar una implementación concreta que muestre los cuadros de mensaje. Esto deja intacta la capacidad de prueba de la unidad.

Editar: La primera pregunta es probablemente demasiado subjetiva para SO. La intención de la interfaz es clara, pero cuándo usarla sería para casos de uso muy específicos. Las propiedades de dependencia generan algo similar y puede ser útil para verificar que el nuevo valor sea válido antes de aplicarlo, pero si está usando propiedades simples, entonces podría simplemente poner esta verificación dentro de su setter. Si un componente diferente necesita verificar la validez, normalmente sería más simple si ese componente realizara el cambio por sí mismo (después de validar el nuevo valor) o si el componente que realiza el cambio lo llama explícitamente para validar el cambio.

-6

Es necesario INotifyPropertyChanged, por ejemplo, si desea saber cuándo se modificará cualquier variable porque puede usar PropertyChangedEventHandler. De esta manera, puede volver a cargar la GUI mientras ejecuta el programa si existe alguna propiedad de dependencia que esté vinculada a cualquier elemento GUI.

Para la última pregunta, creo que puede escribir un archivo de registro con sus mensajes definidos y si desea mostrarle al usuario cualquier alerta puede usar controles como el resumen de errores o la información sobre herramientas. Pero si solo necesita esto para probar, puede mantener las alertas bajo con try y catch blocks.

+1

OP pregunta por la interfaz 'INotifyPropertyChanging', no' INotifyPropertyChanged' –

+1

Haciendo caso omiso del error inocente de la interfaz incorrecta, profundizar en los archivos de registro en este escenario e intentar/capturar excepciones inexistentes para la validación de propiedades no es muy aconsejable. – JRoughan

1

INotifyPropertyChanging se invoca justo antes de que una propiedad cambie. Importante por qué? Para que un controlador de eventos externo pueda lanzar una excepción y evitar el cambio. ¿Y por qué querrías hacer eso? Algún día podría ser la única solución a un error en la base de código de otra persona, por lo que no se apresure a eliminar la escotilla de escape.

+5

Lanzar una excepción en un controlador de eventos para finalizar la ejecución del evento firer me parece un olor a código masivo, incluida la opción de hacer esto * por si acaso * me parece peor. –

3

INotifyPropertyChanging es una optimización para utilizar con Linq a SQL. Cuando un objeto implementa esta interfaz, utiliza el evento cambiante como la señal para almacenar en caché el valor anterior de la propiedad. Si el objeto no implementa esta interfaz, siempre almacenará en caché los valores de las propiedades, aumentando el uso de la memoria. Ver How does INotifyPropertyChanging interface helps limit memory consumption para más detalles.

Cuestiones relacionadas