2016-03-03 29 views
0

我目前有一個使用MVVM的WPF項目。在我的項目,我利用它充當我的應用程序所使用的各種控件集合緩存靜態類的,這樣的事情:試圖瞭解如何將rx.net與現有MVVM項目相結合

public static class AppCache 
{ 

    public static ObservableCollection<MyObject> MyObjects { get; set; } 

    private static async void GetMyObjectsAsync() 
    { 
     await Task.Run(() => GetMyObjects()); 

     Mediator.Instance.NotifyColleagues("MyObjectsUpdatedMessage", true); // A helper class that implements messaging 
    } 

    private static GetMyObjects() 
    { 

     // Get objects via service call 

     ... 

     MyObjects = result; 
    } 

    static AppCache() 
    { 
     MyObjects = new ObservableCollection<MyObject>(); 

     GetMyObjectsAsync(); 
    } 

} 

然後我訂閱調解員在我的各種的ViewModels:

public class MyViewModel : ViewModelBase 
{ 

    ... 

    public ObservableCollection<MyObject> MyObjects 
    { 
     // My ViewModelBase lets me implement INotifyPropertyChanged like this 
     get { return GetValue(() => MyObjects); } 
     set { SetValue(() => MyObjects, value); } 
    } 

    [Message("MyObjectsUpdatedMessage")] 
    private void OnMyObjectSourceUpdated(bool c) 
    { 
     MyObjects = AppCache.MyObjects; 
    } 

    public MyViewModel() 
    { 
     Mediator.Instance.RegisterHandler<bool>("MyObjectsUpdatedMessage", OnMyObjectSourceUpdated); 
    } 

} 

我有這種方法的問題是,當我做收藏的東西在的ViewModels(如添加或編輯MyObject),那麼我要回去和手動更新的全球應用程序緩存的收集和確認它與ViewModel中的內容相匹配,然後確保使用此集合更新所有其他ViewModel以使用新的v ALUE因爲沒有約束力的參與:MyOtherViewModel.MyObjects = AppCache.MyObjects

另一種方法是使GetMyObjectsAsync()公衆和有應用程序緩存從後透過我的視圖模型的變化更新數據庫本身,然後使用調停更新使用集合中的所有其他視圖。我不喜歡這個,因爲這意味着我最終會打出一個我不想要的服務電話。

我想知道的是,如果有任何方法可以使用Reactive Extensions來簡化我的過程,這樣我可以在我的ViewModels訂閱的AppCache中定義某種Reactive屬性,以及何時更新會將其更新推送到所有ViewModel,這是我可用的兩個選項之間的混合(手動更新AppShared集合,但是不需要中介者就通知其所有子集)。

我想我真正想要的是在ViewModel之間有一個基本上可綁定和共享的屬性。

是否有任何種類的可用於實現這種事情的反應性屬性?喜歡的東西:

編輯:

我能得到的訂閱工作如下,但是這又是類似於使用調解員,因爲我有打電話給NotifyMyObjectChanged每當我更新MyObjects的選項。有沒有辦法讓MyObjectsObservable'偵聽'對MyObjects的更改並自動調用NotifyMyObjectChanged?如果沒有辦法做到這一點,通過Mediator使用RX有什麼好處?

public static class AppCache 
{ 

    public static ObservableCollection<MyObject> MyObjects { get; set; } 

    public static IObservable<ObservableCollection<MyObject>> MyObjectsObservable => _mySubject; // C# 6 syntax 

    public static Subject<ObservableCollection<MyObject>> _mySubject { get; set; } 

    private static async void GetMyObjectsAsync() 
    { 
     await Task.Run(() => GetMyObjects()); 

     NotifyMyObjectChanged() // this basically just replaces the mediator 
    } 

    private static GetMyObjects() 
    {     
     ...   
     MyObjects = result; 
    } 

    private static void NotifyMyObjectChanged() 
    { 
     _mySubject.OnNext(MyObjects); 
    } 

    static AppCache() 
    { 
     _mySubject = new Subject<ObservableCollection<MyObject>>(); 

     GetMyObjectsAsync(); 
    }  

} 

public class MyViewModel : ViewModelBase 
{ 

    ObservableCollection<MyObject> MyObjects 
    { 
     get { return GetValue(() => MyObjects); } 
     set { SetValue(() => MyObjects, value); } 
    } 


    IDisposable _subscription { get; } 

    MyViewModel() 
    { 
     _subscription = AppCache.MyObjectsObservable.Subscribe (HandleMyObjectChanged); 
    } 

    private void HandleMyObjectChanged(ObservableCollection<MyObject> myObjects) 
    { 
     MyObjects = myObjects; 
    } 

    public void Dispose() 
    { 
     _subscription.Dispose(); 
    } 
} 
+0

IMO這是一款很好用RX的,但你的問題非常廣泛,所以可能不適合SO職位。 – CodingGorilla

+0

對不起,我會盡量讓我的問題更具體 –

+0

還請考慮http://reactiveui.net/建立在system.reactive – kenny

回答

1

所以你想做的事是這樣的:

public static class AppCache 
{ 
    static AppCache() 
    { 
     _mySubject = new Subject<MyObject>(); 
    } 

    private static void NotifyMyObjectChanged(MyObject object) 
    { 
     _mySubject.OnNext(object); 
    } 

    public static IObservable<MyObject> MyObjectsObservable 
    { 
     get { return _mySubject; } 
    } 
} 

public class MyViewModel : ViewModelBase 
{    
    MyViewModel() 
    { 
      _subscription = AppCache.MyObjectsObservable. 
       .Where(x => x == value) 
       .Subscribe (HandleMyObjectChanged); 
    } 

    private void HandleMyObjectChanged(MyObject object) 
    { 
     ... do work here .... 
    } 

    public void Dispose() 
    { 
     _subscription.Dispose(); 
    } 
} 

在這種情況下,什麼你基本上這裏做的是發送到您的視圖模型通知您MyObject事情有了變化。您可以從處理程序獲取object變量,並使用該變量將更改後的屬性複製到視圖模型中。或者,您可以發送一個包含屬性列表和新值的「消息」類,這可能比發送整個對象輕一點。

另一件需要記住的事情是Observable可能會在UI線程以外的線程上發送「事件」。有一個覆蓋Subscribe,可讓您指定TaskScheduler使用,因此您可以指定UI調度程序,因此您不必自己進行編組。

正如我在我的評論中所說的,有很多方法可以做到這一點,所以你必須四處尋找最適合你需求的東西,但希望這可以給你一些方向。

UPDATE

所以這裏是一個有點更新到您AppCache代碼(從您的編輯),但你的問題基本上是你想擺脫調解員,並與RX更換。最後,你最終還是得到了某種中介,你只需要決定RX是否給你的東西比你自己的中介實現更多。 會(並且確實)使用RX,但它確實是一個偏好的事情,所以你將不得不自己做一些研究。

這說明你使用Observable.FromEventPattern功能,這是非常有用的,給你一個很好的捷徑:

public static class AppCache 
{ 

    ObservableCollection<MyObject> MyObjects { get; set; } 

    public static IObservable<ObservableCollection<MyObject>> MyObjectsObservable { get; private set; } 

    private static async void GetMyObjectsAsync() 
    { 
     await Task.Run(() => GetMyObjects()); 

     NotifyMyObjectChanged() // this basically just replaces the mediator 
    } 

    private static GetMyObjects() 
    {     
     ...   
     MyObjects = result; 
     MyObjectsObservable = Observable.FromEventPattern(h=>MyObjects.CollectionChanged += h, h=>MyObjects.CollectionChanged -= h); 
    } 

    static AppCache() 
    { 
     GetMyObjectsAsync(); 
    }  

} 

我想告訴你的usuage但是這個代碼是不完美的,如果訂戶打電話訂閱MyObjectsObservable之前創建,顯然它會炸燬。

這裏還有一個鏈接,顯示了很多的東西,RX可以做到,那我使它成爲一個很好的工具:http://www.introtorx.com/uat/content/v1.0.10621.0/04_CreatingObservableSequences.html#

+0

這裏要注意的一點是'.Where(x => x == value)''可能無法工作,除非你重寫'Equals'方法,因爲它會回落到引用比較。通常我會使用'Where(x => x.Id == value.Id)''但我不知道你的對象模型。 – CodingGorilla

+0

感謝@CodingGorilla的回覆。如果沒有setter,我該如何使用這種技術將值添加到'MyObjectsObservable'?我使用Publish()方法嗎?如果這個問題看起來很基本,我很抱歉,但我只是在rx世界中只有一天的時間。 (是的,我的確使用了Id的方式) –

+0

@AleksandrAlbert查看我的更新,這是一個更完整的例子,介紹如何實現'IObservable'。我使用'Subject '這是實現它的「捷徑」,並不總是最有效的使用方法,但它也是一個很好的開始。 https://msdn.microsoft.com/en-us/library/hh211700(v=vs.103).aspx – CodingGorilla

相關問題