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


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

JavaScript中的原型鏈

談到『共享』兩字,腦海里跳出第一個印象就是『繼承』。對吧,因為你是父母的孩子,所以理所當然你可以和父母共享家中的一切。所以『共享』的前提,就是構建一個『繼承鏈』,也就是JavaScript中的『原型鏈』。

那么JavaScript是怎樣實現原型鏈呢?有經驗的JavaScript程序員想必早就記的滾瓜爛熟了——通過內置屬性 __proto__ 來實現。

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

為ViewModel構建繼承關系

有了上述的分析之后,只要仿照JavaScript的 __proto__ 的實現,我們對所有ViewModel的基類ViewModelBase添加一個ParentViewModel 屬性,它代表當前ViewModel的父親對象。

public class ViewModelBase
{
    public ViewModelBase ParentViewModel { get; set; }
	//...
}

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

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

可以看到通過 FindAncestor 方法,去指定 AncestorType 類型的上層對象中獲取數據。

所以,我為ViewModelBase 增加一個擴展方法,可以通過繼承鏈實現從指定的祖先對象獲取數據。

    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擴展方法獲取上層對象的數據

var ancestors = this.Ancestors<FaceBoxViewModel>();

最后,以圖示的形式會更加直觀,下圖所示,SubViewModel依靠繼承鏈可以輕松訪問到ParentViewModel的共享數據:

小結

本篇文章介紹了怎樣在ViewModel之間共享數據,實際上解決方案是非常簡單的,人為的構造了一個繼承鏈並隨着繼承鏈往上找,總是能找到希望獲取到的數據。類似與JavaScript中的原型鏈,維護了一種至上而下的父子關系。
源代碼托管在Github上,點擊此了解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM