2012-02-06 28 views
1

之前,我對我的問題/問題,這裏是我的應用程序的基本結構:更新一個標籤從嵌套的視圖模型的財產

在我MainWindow.xaml(在這種情況下,主視圖),我有一個標籤(我知道我應該將其更改爲TextBlock的,但是這是一個單獨的問題):

<Label Name="StatusLabel" Content="{Binding Path=Status}"/> 

它對應的視圖模型(MainWindowViewModel)包含另一個視圖模型(SiteListViewModel)和Status屬性:

public class MainWindowViewModel : ViewModelBase 
{ 
    public SiteListViewModel SiteList { get; set; } 
    public String Status 
    { 
     get { return SiteList.Status; } 
    } 
} 

正如你所看到的,MainWindowViewModel的狀態屬性返回SiteListViewModel情況下,狀態屬性,它的定義是這樣的:

public class SiteListViewModel : ViewModelBase 
{ 
    private string status; 
    public String Status 
    { 
     get { return this.status; } 
     set 
     { 
      this.status = value; 
      base.OnPropertyChanged("Status"); 
     } 
    } 
} 

SiteListViewModel的狀態屬性中異步進程在不同的地方更新,以使用戶瞭解,以什麼正在進行。這是簡單的任務調用,如做:

Status = String.Format(Properties.Resources.SiteListViewModel_Status_LoadingJobs, count + 1, totalSites); 

另外要注意,無論MainWindowViewModel和SiteListViewModel從ViewModelBase其實現INotifyPropertyChanged繼承。

現在的實際問題/問題:

標籤不更新。

但是,如果我改變視圖結合本:

<Label Name="StatusLabel" Content="{Binding Path=SiteList.Status}"/> 

它工作正常。這似乎表明我在MainWindowViewModel級別缺少一些東西。我可以保持它原來的狀態,但是這會延伸到子視圖模型的結構中,這不是我想要做的事情。

有人能指出我做錯了什麼嗎?

回答

3

當然,它不會更新,綁定系統監聽您綁定到擁有該屬性的類型的屬性的更改事件,您根本不會觸發任何通知。

你可以轉發嵌套VM的通知:

public MainWindowViewModel 
{ 
    SiteList.PropertyChanged += (s,e) 
     => if (e.PropertyName == "Status") OnPropertyChanged("Status"); 
} 

哪裏OnPropertyChanged是提高PropertyChanged的方法;你的VM基類應該有這樣的東西。

雖然我建議放棄屬性,但它是多餘的,因爲你可以直接綁定,雖然SiteList(也屬性應該在其setter觸發更改通知)。你也需要從舊實例中分離處理程序,並在SiteList發生改變(可以在setter中完成)時將其重新附加到新實例。

+0

我知道,如果我直接綁定到'SiteList.Status'它會工作(我說這附近的後結束),但感覺像我正在通過這樣做打破封裝。我想我對PropertyChanged事件的處理方式瞭解甚少。我認爲只要它在XAML/UI級別綁定到「父」屬性,事件的「級別」並不重要。 – 2012-02-06 20:27:39

+0

+1把這個關掉我的「未答覆的問題」列表。因爲你的回答與我在同一時間做的幾乎一樣:) – Rachel 2012-02-06 20:29:33

0

僅僅因爲某些東西實現了INotifyPropertyChanged並不意味着它會自動知道屬性何時更改。您需要在代碼中引發PropertyChanged事件。

在您的示例中,只要狀態發生更改,即可通過註冊SiteListViewMode.PropertyChanged並針對Status發出PropertyChanged通知來完成。

public class MainWindowViewModel : ViewModelBase 
{ 
    public SiteListViewModel SiteList { get; set; } 
    public String Status 
    { 
     get { return SiteList.Status; } 
    } 

    public MainWindowViewModel() 
    { 
     // Of course, verify property isn't null first. 
     // Also, it's probably best to attach this in the setter 
     // so you can unhook the event from old items too 
     SiteList.PropertyChanged += SiteList_PropertyChanged; 
    } 

    void SiteList_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "Status") 
      RaisePropertyChanged("Status"); 
    } 
} 
0

因爲MainWindowDataContextMainWindowViewModel。然後

Label將「繼承」相同DataContext,所以LabelDataContex噸也MainWindowViewModel。這就是爲什麼你必須做SiteList.Status。 (因爲你沒有提出在MainWindowViewModelPropertyChanged但在SiteListViewModel。)

+0

這不是重點,MainWindowViewModel上也存在'Status'。 – 2012-02-06 20:09:42

+0

right-o。小的更新來解釋爲什麼一種語法的作品,但不是另一種。 – 2012-02-06 20:11:59