2011-11-29 30 views
17

En mi modelo de vista MVVM que tienen como campo decómo implementar observable int en wpf ViewModel?

public int Delta { get; private set; } 

Sin embargo, cuando pongo al día de esa manera:

Delta = newValue; 

interfaz de usuario no se actualiza.

Estaba pensando que la unión de datos lo haría por mí. Por ejemplo, puedo declarar la colección como ObservableCollection y luego el enlace de datos funcionará.

Sin embargo, no hay ObservableInt, ¿cómo decir Vista que necesita ser actualizado entonces?

Probablemente debería plantear algún evento "notificación de cambio de propiedad" o algo?

+0

Sí, usted está en el camino correcto. Necesita levantar un evento cambiado propiedad. google INotifyPropertyChanged –

+0

pero ¿cómo sabrá View que cuando cierta propiedad se levanta cierto control necesita ser udpated? – javapowered

+0

La vista lo sabrá a través de los enlaces que tiene. – BigL

Respuesta

31

Usted tiene dos opciones:

  1. implementar la interfaz INotifyPropertyChanged en su clase.
  2. Heredar de DependencyObject e implementar Delta como DependencyProperty.

La opción más simple es # 1. Puede implementar la interfaz INotifyPropertyChanged en su clase con bastante facilidad:

public class YourClass : INotifyPropertyChanged 
{ 

    private int _delta; 
    public int Delta 
    { 
     get { return _delta; } 
     set { _delta = value; NotifyPropertyChanged("Delta"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    } 

Puede leer más sobre using and implementing dependency properties en MSDN.

+3

+1 Absolutamente correcto, pero para cualquiera que sea nuevo en WPF, le sugiero que revise también las otras respuestas, ya que la adopción de un conjunto de herramientas existente requerirá menos trabajo y facilitará el aprendizaje del marco. – jeremyalan

+0

¿puedo omitir la creación de 'private int _delta;' de alguna manera? Quiero que esto sea generado automáticamente por C#, como propiedad normal – javapowered

+1

@javapowered: Desafortunadamente, no. No puede tener una auto-propiedad "parcialmente implementada". Y si necesita invocar métodos en el setter (como en este caso), debe proporcionar tanto el campo de respaldo como la implementación de la propiedad. – LBushkin

3

Simplemente implemente INotifyPropertyChanged Interface en su clase y úselo para generar un PropertyChanged para su Propiedad y luego la IU se actualizará. Si está utilizando una plantilla de proyecto MVVM, es muy probable que ya tenga implementado un método de ayuda, solo necesita usarlo.

MSDN INotifyPropertyChanged

GalaSoft MVVM Light Toolkit

2

El ObservableCollection provoca eventos automáticamente, pero para sus propias propiedades hay que levantar los eventos usted mismo.

Un buen ejemplo es aquí: http://www.codeproject.com/Tips/228352/Naming-Properties-in-MVVM?display=Print

me gustaría sugerir el uso de luz MVVM: http://mvvmlight.codeplex.com, que utilizaban en Silverlight y aplicaciones WPF. Muy fácil de usar y proporciona un sistema de mensaje entre el modelo, el modelo de vista y la vista.

+1

Solo un recordatorio, que incluso en un ObservableCollection necesita aumentar la propiedad cambiada en caso de que cambie la referencia a la colección. –

2

Usando @ respuesta de LBushKin, he modificado a

public class Prop<T> : INotifyPropertyChanged 
{ 
    private T _value; 
    public T Value 
    { 
     get { return _value; } 
     set { _value = value; NotifyPropertyChanged("Value"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    internal void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

y configurarlo:

class MainWindow ... 
    // a bool with initial value of true 
    public static Prop<bool> optionBool { get; set; } = new Prop<bool>{ Value = true }; 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     // connect 
     DataContext = this; 
    } 

y utilizarlo:

<Grid ... 
    <CheckBox Content="Da Check" ... IsChecked="{Binding optionBool.Value}"/> 
0

Ya que estamos en con la mejora de la respuesta, algunas de las otras nuevas adiciones de C# 6.0 y 7.0 ayudar a que sea cada vez más compacta:

public class Prop<T> : INotifyPropertyChanged 
{ 
    private T _value; 

    public T Value 
    { 
     get => _value; 
     set { _value = value; NotifyPropertyChanged(nameof(_value)); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    internal void NotifyPropertyChanged(String propertyName) => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

esta manera, usted no está utilizando ningún "valores" (es decir embbeded - nombre de la propiedad) y está manteniendo el refactor de fallos de código.

Y tampoco hay necesidad de que los bloques de código redundantes debido a C# 6.0 y nuevo cuerpo Expresión de 7.0 cuenta con

Cuestiones relacionadas