Windows 10 UWP 23 of N: Visual layer part 1 without XAML

  • 217
  • 0
  • UAP
  • 2021-04-30

Introduce composition / visual layer api for UWP app. This one sample without using xaml.

這次要來介紹Composition API,這支API是在1511(10586)的時候就已經介紹出來!但是在1607(14393)的更新時變更了XAML interrop的流程~今天先簡單介紹Composition的強大能力!


XAML由Microsoft從WPF時代開始引入至Framework層開始可以做出MVVM的框架,而這樣的框架其實也是從MVC演進過來!但是Composition必須要由UI code-behide的方式來使用~Microsoft composition team的目標是把所有在UWP的XAML都控制項都能和Composition配合!

這邊開始介紹Composition是怎樣的一個概念~

UI framework layering: the framework layer (Windows.UI.XAML) is built on the visual layer (Windows.UI.Composition) which is build on the graphics layer (DirectX)上圖出自 Docs Microsoft

UWP在1511(10586)開始加入中間層Visual layer的方式可以讓某些Graphic layer的特效以及繪圖能力能夠提升到讓Framework layer也能較為簡單操作的模式! 而XAML的 Visual Tree和 Composition的Visual tree是完全不相同的!

但是XAML的UI contorl可以和Composition的Visual tree互動之後系列文章會提及~XAML本身在建構Control是非常方便的但能互動的效果大多都是Transition為主,而XAML本身封裝了較多的功能(GPU的Render以及VisualState的實作)所以相較Visual layer來說較為肥大。

話不多說先來看看如何在非XAML的UWP APP下使用Composition八~


先是把App.xaml以及MainPage.xaml刪除掉!

接者建立一個 Class  MainEntry裡面只有Main()的方法!

public class MainEntry
    {
        public static void Main()
        {
            CoreApplication.Run(new CoreWindow());
        }
    }

基本上UWP跟其他應用程式都是可以透過Main進入執行狀態,只是專案範本( Template )本身很方便的幫忙建立App.xaml以及App.xaml.cs作為App的進入點。

移除掉了XAML的Page的方式就得使用CoreApplication.Run來執行APP,這邊我實作了一個Class名為CoreWindow。

public class CoreWindow : IFrameworkViewSource
    {
        public IFrameworkView CreateView()
        {
            return new CoreWindowView();
        }
    }

在CoreWindow裡面需要實作IFrameworkViewSource來提供應用程式做View的物件,這個Interface基本上就是UWP的Application view的Factory!接下來在實作另一物件 CoreWindowView

public class CoreWindowView : IFrameworkView
    {
        public void Initialize(CoreApplicationView applicationView)
        {

        }

        public void Load(string entryPoint)
        {

        }

        public void Run()
        {
            
        }

        public void SetWindow(Windows.UI.Core.CoreWindow window)
        {
            
        }

        private void CreateRectangle()
        {
            
        }

        private void CreateBackgroundVisual()
        {
            
        }

        private void InitializeComposition()
        {
            
        }

        public void Uninitialize()
        {

        }
    }

CoreWindowView實作了IFrameworkView的interface!這個interface提供View的生命週期( Live management )所以先會執行Initialize -> SetWindow -> Load -> Run -> Uninitialize這樣的流程。

接者可以在SetWindow來開刀!因為Initialize的時期並不會知道CoreApplication產生的Window是否會帶給這個View。所以SetWindow的Code如下

public void SetWindow(Windows.UI.Core.CoreWindow window)
        {
            coreWindow = window;
            InitializeComposition();
            CreateBackgroundVisual();
            CreateRectangle();
        }

接者開始是使用Composition API!

private void InitializeComposition()
        {
            compositor = new Compositor();
            rootVisual = compositor.CreateContainerVisual();
            compositionTarget = compositor.CreateTargetForCurrentView();
            compositionTarget.Root = rootVisual;
        }

先是建立Compositor,這個物件是所有Composition API 的Root所以之後的Composition都會使用到該物件為出發點! 這邊需要注意的是需要利用Compositor建立一個ContainerVisual 這個物件也就是所有visual的container!所以所有的visual都會被放入到這個container裡面~

然後需要再使用Compositor來建立View和Composition API的關係,因為Window以及View並非是由XAML提供得所以需要手動將關係建立起來!

接者來建立View的背景的顏色吧

private void CreateBackgroundVisual()
        {
            var backgroundVisual = compositor?.CreateSpriteVisual();
            var backgroundBrush = compositor?.CreateColorBrush(Windows.UI.Colors.LightGray);
            backgroundVisual.Brush = backgroundBrush;
            backgroundVisual.Size = new Vector2((float)coreWindow.Bounds.Width, (float)coreWindow.Bounds.Height);
            rootVisual?.Children.InsertAtBottom(backgroundVisual);
        }

使用SpriteVisual這個簡單的API產生出Visual並且給上Brush以及Size之後在放入到container visual內,這邊使用到的Size都是使用向量!!!然後放到container visual的最後一個Children喔。

接者在來看看建立一個Rectangle在畫面上八

private void CreateRectangle()
        {
            var rectangle = compositor?.CreateSpriteVisual();
            var rectangleBrush = compositor?.CreateColorBrush(Windows.UI.Colors.Red);
            rectangle.Brush = rectangleBrush;
            rectangle.Size = new Vector2(100, 100);
            rectangle.Offset = new Vector3((float)coreWindow.Bounds.Width / 2.0f - rectangle.Size.X / 2.0f, (float)coreWindow.Bounds.Height / 2.0f - rectangle.Size.Y / 2.0f, 0);
            rootVisual.Children.InsertAtTop(rectangle);
        }

如上面的Code所示!建立一個Visual之後給上顏色、大小、偏移值然後在放到container visual內!

最後執行結果如下


可以發現到沒有使用到XAML的APP使用的記憶體使用量真的很少!而Composition所提供的功能真的是強大到不行所以很多動畫的都盡量交給Composition API來完成八~

 

 

 

***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio版本有所調整!***

參考資料 MSDN

下次再分享Windows 10 的新技術拉~