2011-11-29 93 views
17

在我的MVVM的ViewModel我有這樣的場如何在wpf ViewModel中實現observable int?

public int Delta { get; private set; } 

然而,當我更新這樣的:

Delta = newValue; 

UI不會刷新。

我在想數據綁定會爲我做。例如,我可以將收集聲明爲ObservableCollection,然後進行數據綁定。

但是沒有ObservableInt,怎麼說查看它需要刷新呢?

也許我應該提出一些事件「通知財產變」或什麼?

+0

是的,你是在正確的軌道上。你需要提出一個屬性改變的事件。谷歌INotifyPropertyChanged –

+0

但View如何知道當某些屬性被提高某些控制需要被解決? – javapowered

+0

該視圖將通過您擁有的綁定知道它。 – BigL

回答

31

你有兩個選擇:

  1. 實現你的類INotifyPropertyChanged接口。
  2. 繼承DependencyObject並將Delta實現爲DependencyProperty。

最簡單的選項是#1。您可以實現INotifyPropertyChanged接口的類很容易:

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)); 
     } 
    } 
    } 

你可以閱讀更多關於using and implementing dependency properties MSDN上。

+3

+1絕對正確,但對於任何新來WPF的人來說,我鼓勵您也查看其他答案,因爲採用現有的工具包將需要較少的工作並使得學習框架變得更容易。 – jeremyalan

+0

可以省略'private int _delta;'創建嗎?我希望這是由C#自動生成的,就像普通的屬性 – javapowered

+1

@javapowered:不幸的是,沒有。您不能擁有「部分實施」的自動屬性。如果你需要在setter中調用方法(就像在這種情況下),你必須提供後臺字段和屬性實現。 – LBushkin

3

只需在您的類中實現INotifyPropertyChanged接口並使用它爲您的Property引發PropertyChanged,然後UI將會更新。如果您正在使用MVVM項目模板,那麼很可能您已經實現了一個輔助方法,您只需要使用它。

MSDN INotifyPropertyChanged

GalaSoft MVVM Light Toolkit

2

ObservableCollection自動引發事件,但對於自己的屬性,你必須提高自己的事件。

一個很好的例子是在這裏:http://www.codeproject.com/Tips/228352/Naming-Properties-in-MVVM?display=Print

我建議使用MVVM光:http://mvvmlight.codeplex.com,我用它在Silverlight和WPF應用程序。非常易於使用,並提供模型,視圖模型和視圖之間的消息系統。

+1

提醒一下,即使在ObservableCollection中,如果引用集合本身發生更改,您也需要提升屬性。 –

2

使用@ LBushKin的答案,我修改了它

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)); 
    } 
} 

,並對其進行設置:

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; 
    } 

,並使用它:

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

雖然我們在它與改進的答案,一些其他新的c#6.0和7添加。0幫助使其更加緊湊:

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)); 
} 

這樣,你沒有使用任何「embbeded值」(即 - 屬性的名稱),並保持代碼重構安全。

還有的也無需冗餘代碼塊由於C#6.0和7.0的新的表達機身特點