2015-12-03 45 views
1

最近我一直在學習C#和WPF的工作。我正在嘗試在我正在開發的項目上使用MVVM,只是爲了保持代碼的有序性並瞭解它的工作原理。多次調用PropertyChanged的ViewModel屬性

在MVVM中,View上的控件綁定到實現INotifyPropertyChanged的ViewModel上的屬性。很多時候,當某個屬性更新時,我會希望一堆其他屬性作爲結果進行更新。

例如,我有一個ListBox上面有一個TextBox。您可以輸入文本框,並過濾列表框中的內容。但是在某些情況下,我還需要能夠從代碼中清除文本框。代碼最終看起來是這樣的:

private Collection<string> _listOfStuff; 
public Collection<string> FilteredList 
{ 
    get 
    { 
     if (String.IsNullOrWhiteSpace(SearchText)) 
     { 
      return _listOfStuff; 
     } 
     else 
     { 
      return new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText))); 
     } 
    } 
    set 
    { 
     if (value != _listOfStuff) 
     { 
      _listOfStuff = value; 
      OnPropertyChanged("FilteredList"); 
     } 
    } 
} 

private string _searchText; 
public string SearchText 
{ 
    get { return _searchText; } 
    set 
    { 
     if (value != _searchText) 
     { 
      _searchText = value; 
      OnPropertyChanged("SearchText"); // Tells the view to change the value of the TextBox 
      OnPropertyChanged("FilteredList"); // Tells the view to update the filtered list 
     } 
    } 
} 

隨着這個項目變得越來越大,這開始感覺馬虎。我有一個接線員,打了6個電話給OnPropertyChanged,並且很難跟蹤東西。有一個更好的方法嗎?

+0

通過馬虎你是指很多OnPropertyChanged語句?那這正是你想要的不是? – Muds

+0

你不必調用'OnPropertyChanged(「FilteredList」);'因爲它沒有改變/分配。當它被改變時(即在一個異步命令中),當你執行'FilteredList = await SomeAsyncMethod()'時,它會被通知。你到底想要歸檔什麼? – Tseng

+0

@Tseng我必須調用OnPropertyChanged(「FilteredList」);'因爲它的值取決於SearchText的內容 –

回答

1

我嘗試了Assisticant在大約一年前項目。它會計算出哪些屬性需要提出通知以及哪些相關。在Pluralsight上有一個很好的課程,網站上的例子非常好。如果沒有別的,你可以查看源代碼,看看他是如何做到的。

還有一些來自Change Notification in MVVM Hierarchies的好建議。

他們提到:
使用屬性 - >例如[DependsUpon(nameof(尺寸))]

約什 - 史密斯的PropertyObserver

能不能把一個方法加薪屬性更改電話如果你只需要每次都提出同樣的通知。

-2

如果你只是不想輸入其他選項是引發OnPropertyChanged的所有屬性,可以通過傳遞一個null或string.Empty來完成,儘管它會是一個斜坡的代碼!

OnPropertyChanged(Null); 

OnPropertyChanged(String.Empty); 
0

首先你不應該在一個命令執行可能造成昂貴的操作,那麼您就可以從你的SearchText刪除OnPropertyChanged("FilteredList");

因此,您應該將該代碼從getter移動到它自己的命令中,並將其從XAML綁定(或者作爲按鈕上的命令,或者使用Blends Interactivity Trigger在文本字段值發生更改時調用它)。

public ICommand SearchCommand { get; protected set; } 
// Constructor 
public MyViewModel() 
{ 
    // DelegateCommand.FromAsyncHandler is from Prism Framework, but you can use 
    // whatever your MVVM framework offers for async commands 
    SearchCommand = DelegateCommand.FromAsyncHandler(DoSearch); 
} 

public async Task DoSearch() 
{ 
    var result = await _listOfStuff.Where(x => x.Contains(SearchText)).ToListAsync(); 
    FilteredList = new Collection<string>(result); 
} 

private Collection<string> _listOfStuff; 
private Collection<string> _filteredList; 
public Collection<string> FilteredList 
{ 
    get 
    { 
     return _filteredList; 
    } 
    set 
    { 
     if (value != _filteredList) 
     { 
      _filteredList = value; 
      OnPropertyChanged("FilteredList"); 
     } 
    } 
} 

private string _searchText; 
public string SearchText 
{ 
    get 
    { 
     return _searchText; 
    } 
    set 
    { 
     if (value != _searchText) 
     { 
      _searchText = value; 
      OnPropertyChanged("SearchText"); 
     } 
    } 
} 

在一個側面說明:您還可以使用OnPropertyChanged(nameof(FilteredList));有一個重構友好的版本,當你重命名你的財產所有OnPropertyChanged通話將被更新到。雖然需要C#6.0,但它與舊的.NET Frameworks(回到2.0)兼容,但需要Visual Studio 2015或更高版本

0

您應該只在屬性本身的setter中提升OnPropertyChanged

一個清潔的實現您的視圖模型可以是:

private Collection<string> _listOfStuff; 
private Collection<string> _filteredList; 

public Collection<string> FilteredList 
{ 
    get 
    {   
      return _filteredList; 
    } 
    set 
    { 
     if (value != _filteredList) 
     { 
      _filteredList = value; 
      OnPropertyChanged("FilteredList"); 
     } 
    } 
} 

private string _searchText; 
public string SearchText 
{ 
    get { return _searchText; } 
    set 
    { 
     if (value != _searchText) 
     { 
      _searchText = value; 
      OnPropertyChanged("SearchText"); 

      FilteredList = new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText))); 
     } 
    } 
} 
1

對於任何尋找此類問題的良好解決方案的人:請查看ReactiveUI

它是一個基於Reactive Extensions(Rx)的框架,其思想是明確地在屬性之間建立這種類型的依賴關係,而沒有RaisePropertyChanged(..)的叢林。

特別檢查一下ObservableAsPropertyHelper(有時稱爲OAPH)。