2013-11-01 150 views
1

在reactiveui和反應式擴展中,您可以將多個observable組合成一個。使用像CombineLatest或Zip這樣的函數,可以使得得到的可觀察值使用函數來根據來自組合觀測值的值計算結果。儘管CombineLatest給了你一個觀察值,每當任何一個組合的可觀測值被觸發時它都會給你通知,但只有當所有這些可觀測值至少觸發一次時它纔開始工作。我希望它從一開始就發出通知 - 給出可觀察到的初始值或其他值。當然,我可以以某種方式讓這些可觀察的火焰來設定初始值。但有時候並不那麼容易,或者它使代碼看起來很難看。這裏有一個例子: 我正在使用reactiveui製作一個wpf應用程序。在我的一個視圖模型中,我試圖通過組合observables來創建屬性。所以,我有一個具有NumberToSum屬性的對象的集合(ReactiveList),我需要一個屬性來顯示該屬性值的總和。該集合中的對象也是視圖模型,它們的NumberToSum屬性可以由用戶更改。用於總和的對象數量由其他屬性確定。這就是我試圖做到這一點:有沒有辦法指定被動擴展observables的初始值?

private readonly ReactiveList<Element> _collection = new ReactiveList<Element>(); 
private readonly ObservableAsPropertyHelper<int> _sum; 
private int _elementsToTake = 0; 

public int ElementsToTake 
{ 
    get { return _elementsToTake; } 
    set { this.RaiseAndSetIfChanged(ref _elementsToTake, value) } 
} 

public int Sum 
{ 
    get { return _sum.Value; } 
} 

public MyViewModel 
{ 
    var elementsToTakeObservable = this 
     .WhenAny(x => x.ElementsToTake, x => x.Value); 
    _collection.ChangeTrackingEnabled = true; 
    //here I'm adding some objects to _collection 
    var sumObservable = _collection.ItemChanged 
     .CombineLatest(elementsToTakeObservable, 
      (_, c) => _collection.Take(c) 
       .Aggregate(0, (i, x) => i + x.NumberToSum))). 
     .ToProperty(this, x => x.Sum, out _sum, 0); 
} 

所以,我使用ReactiveList.ItemChanged跟蹤_collection項目的變化。每次發生變化時,重新計算總和。這裏的問題是觀察值的初始值合併到sumObservable中。通過將值賦給ElementsToTake屬性,我可以輕鬆設置elementsToTakeObservable的初始值,這會引發屬性更改的事件和內容。但是爲_collection.ItemChanged做可觀察的事情並不容易。我需要讓_collection中的至少一個對象引發propertychanged事件,但這看起來很糟糕。 是否可以設置這些初始值?或者,也許我完全錯了嗎?

回答

7

StartWith將解決您的問題。此外,我不確定是否需要ItemChanged,它表示當列表中的項目發生更改時,而不是項目添加或刪除時。在這裏,你可能也想聽Changed

儘管試圖以這種方式保持「跑步總數」,但實際上由於重置和移動而難以正確執行此操作。一種更簡單的方法是濫用的事實,CPU是真快,只是重新計算它的每一個變化:

_collection.ChangeTrackingEnabled = true; 

Observable.Merge(
     _collection.Changed.Select(_ => Unit.Default), 
     _collection.ItemChanged.Select(_ => Unit.Default)) 
    .Select(_ => _collection.Sum(x => x.NumberToSum)); 

另一種方法,是不是像這樣聚集很好,但也可以是超級有用,是ActOnEveryObject ,它將對列表中的每個項目執行一個塊,並正確處理初始化,重置和移動。

+0

感謝您將ItemChanged與Change結合使用的提示。 StartWith沒有解決我的問題。或者我只是不明白如何正確使用它。你能舉個例子嗎? – Ukyo

+0

StartWith不是上面代碼唯一的錯誤,但不包括它是CombineLatest爲什麼會出現「不工作」的常見原因,因爲直到它對於「雙方」都有值時,它不會產生任何東西 –

+0

找到StartWith示例,現在一切正常,謝謝! – Ukyo

相關問題