Unity應用架構設計(5)——ViewModel之間如何共享數據

對於客戶端應用程序而言,單頁應用程序(Single Page Application)是最多見的表現形式。有經驗的開發人員每每會把一個View分解多個SubView。那麼,如何在多個SubView之間 『共享數據』 是一個很棘手的事情。又由於ViewModel纔是真正爲View提供數據來源,因此本質上『共享數據』指的是多個ViewModel之間共享同一塊數據控件。javascript

JavaScript中的原型鏈

談到『共享』兩字,腦海裏跳出第一個印象就是『繼承』。對吧,由於你是父母的孩子,因此理所固然你能夠和父母共享家中的一切。因此『共享』的前提,就是構建一個『繼承鏈』,也就是JavaScript中的『原型鏈』。java

那麼JavaScript是怎樣實現原型鏈呢?有經驗的JavaScript程序員想必早就記的倒背如流了——經過內置屬性 __proto__ 來實現。git

因此ViewModel之間『共享數據』的核心就是如何去實現一個繼承鏈,以下所示:程序員

爲ViewModel構建繼承關係

有了上述的分析以後,只要仿照JavaScript的 __proto__ 的實現,咱們對全部ViewModel的基類ViewModelBase添加一個ParentViewModel 屬性,它表明當前ViewModel的父親對象。github

public class ViewModelBase
{
    public ViewModelBase ParentViewModel { get; set; }
    //...
}複製代碼

接着我參考了WPF中是怎樣獲取父ViewModel當中的數據:this

Binding="{Binding RelativeSource={RelativeSource FindAncestor, 
 AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}複製代碼

能夠看到經過 FindAncestor 方法,去指定 AncestorType 類型的上層對象中獲取數據。spa

因此,我爲ViewModelBase 增長一個擴展方法,能夠經過繼承鏈實現從指定的祖先對象獲取數據。code

public static IEnumerable<T> Ancestors<T>(this ViewModelBase origin) where T : ViewModelBase
{
    if (origin==null)
    {
        yield break;
    }
    var parentViewModel = origin.ParentViewModel;
    while (parentViewModel!=null)
    {
        var castedViewModel = parentViewModel as T;
        if (castedViewModel != null)
        {
            yield return castedViewModel;
        }
        parentViewModel = parentViewModel.ParentViewModel;
    }
}複製代碼

對應在ViewModel中,能夠經過 Ancestors擴展方法獲取上層對象的數據cdn

var ancestors = this.Ancestors<FaceBoxViewModel>();複製代碼

最後,以圖示的形式會更加直觀,下圖所示,SubViewModel依靠繼承鏈能夠輕鬆訪問到ParentViewModel的共享數據:xml

小結

本篇文章介紹了怎樣在ViewModel之間共享數據,實際上解決方案是很是簡單的,人爲的構造了一個繼承鏈並隨着繼承鏈往上找,老是能找到但願獲取到的數據。相似與JavaScript中的原型鏈,維護了一種至上而下的父子關係。
源代碼託管在Github上,點擊此瞭解

歡迎關注個人公衆號:

相關文章
相關標籤/搜索