1. 程式人生 > >【Win 10 應用開發】UI Composition 劄記(三):與 XAML 集成

【Win 10 應用開發】UI Composition 劄記(三):與 XAML 集成

單獨使用 切換 column gif 頂部 tel border 靜態 ons

除了 DirectX 遊戲開發,我們一般很少單獨使用 UI Composition ,因此,與 XAML 互動並集成是必然結果。這樣能夠把兩者的優勢混合使用,讓UI布局能夠更靈活。

說到與 XAML 的集成,則我們必須先認識一位夥計,他非常重要,位於 Windows.UI.Xaml.Hosting 命名空間下,名叫 ElementCompositionPreview ,有了它,我們才可以在 XAML 元素與 Composition UI 元素之間遊走。來看看它都公開了哪些成員。

    public sealed class ElementCompositionPreview : IElementCompositionPreview
    {

        
public static void SetImplicitShowAnimation(UIElement element, ICompositionAnimationBase animation); public static void SetImplicitHideAnimation(UIElement element, ICompositionAnimationBase animation); public static void SetIsTranslationEnabled(UIElement element, bool value);
public static CompositionPropertySet GetPointerPositionPropertySet(UIElement targetElement); public static Visual GetElementVisual(UIElement element); public static Visual GetElementChildVisual(UIElement element); public static void SetElementChildVisual(UIElement element, Visual visual);
public static CompositionPropertySet GetScrollViewerManipulationPropertySet(ScrollViewer scrollViewer); }

這個類公開的方法都是靜態的,無需實例調用。我們不要急於弄懂每個方法的作用,這樣會把自己帶入死胡同。此處,我們先重點掌握以下幾個方法的用法。

1、GetElementVisual:要使 XAML 元素與 Composition API 交互,這個方法特別要緊,通過調用它,我們可以得到 XAML 元素中的 Composition UI 樹的表示元素,並且能獲取到關聯的 Compositor 對象,有了關聯的 Compositor實例,我們才能創建各種 UI 元素。

2、SetElementChildVisual:當我們使用 Composition API 創建完自定義的 UI 元素後,要調用這個方法把它插入到 XAML 對象的可視化樹中。註意,UI 元素總是被插入到可視化樹的最後一個位置,因此,我們自己組裝的元素總是會擋住原來的 XAML 元素的。這個你得註意。

3、GetElementChildVisual:只有你調用過 SetElementChildVisual 方法把自定義 Visual 元素加入過可視化樹,才能調用這個方法,這個方法就是返回你上一次插入的元素。如果你沒有插入過自定義的可視化元素,則該方法會返回 null。註意,不要把這個方法跟 GetElementVisual 方法混淆,兩者不同。GetElementVisual 方法是獲得與目標 XAML 對象關聯的可視化對象,而 GetElementChildVisual 方法是獲取你上一次插入到可視化樹的自定義元素。

下面給大夥看一個例子。

在頁面上,我放了一個 Border 對象。

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Border Name="bd" Background="Black"/>
    </Grid>

順便把它的背景設置為黑色,方便後面看電影。

切換到代碼文件,現在我們自定義組裝一下UI,然後插入到 Border 元素的子樹中。

        public MainPage()
        {
            this.InitializeComponent();
            CompositMyVisual();
        }


        void CompositMyVisual()
        {
            Visual visualForbd = ElementCompositionPreview.GetElementVisual(bd);
            // 組建UI
            Compositor compos = visualForbd.Compositor;
            // 根元素
            ContainerVisual rootvs = compos.CreateContainerVisual();
            // 第一個可視化元素
            SpriteVisual v1 = compos.CreateSpriteVisual();
            v1.Brush = compos.CreateColorBrush(Colors.Green);
            v1.Size = new Vector2(450f, 300f); //大小
            v1.Offset = new Vector3(30f, 20f, -1f); //位移
            rootvs.Children.InsertAtTop(v1);
            // 第二個可視化元素
            SpriteVisual v2 = compos.CreateSpriteVisual();
            v2.Brush = compos.CreateColorBrush(Colors.SkyBlue);
            v2.Size = new Vector2(400f, 400f);
            v2.Offset = new Vector3(180f, 125f, 0f);
            rootvs.Children.InsertAtTop(v2);

            // 這一句很重要
            ElementCompositionPreview.SetElementChildVisual(bd, rootvs);
        }

記得,在組裝完UI元素後,要調用 ElementCompositionPreview.SetElementChildVisual方法,把自定義的元素插入到可視化樹中。

在前面的博文中,老周介紹過,ContainerVisual 是個容器元素,它公開一個 Children 集合,我們可以向其中添加子元素,這裏頭有四個方法我們可以調用。

1、InsertAtTop :子元素會始終位於其他元素的頂部,所以這個元素會遮擋住其他元素。

2、InsertAtBottom:所添加的子元素始終在顯示層的底部,它會被其他元素遮擋。

3、InsertAbove:把當前子元素放到某個元素之上。比如我們可以明確指定讓當前元素位於 A 元素之上,這使得當前元素可能遮擋住 A 元素。

4、InsertBelow:把當前元素放到某個元素的下方。如果當前元素放在 A 元素下面,那麽,該元素可能被 A 元素遮擋。

我們看看這個例子的效果。

技術分享

在上面的代碼中,第一個元素是綠色畫刷填充的,第二個是天藍色的,而我們在插入元素樹時,都把它們放到所有元素的頂部。

    rootvs.Children.InsertAtTop(v1);
    rootvs.Children.InsertAtTop(v2);

都位於頂部,那麽後加上去的元素就會擋住前面的元素,所以我們看到,天藍色的那塊區域擋住了綠色區域的一部分。

使用這種交互,我們還可以很輕松地對 XAML 元素進行三維旋轉。

這個例子的界面分為兩部分。左邊咱們放三個滑塊,分別調節 XAML 對象在 X、Y、Z 軸上的旋轉角度,範圍在 -90 到 90 之間。

            <Slider Name="sldX" Header="X 軸" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>
            <Slider Name="sldY" Header="Y 軸" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>
            <Slider Name="sldZ" Header="Z 軸" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>

界面的右邊是一個矩形。

  <Rectangle Grid.Column="1" Width="300" Height="300" Fill="Brown" Name="rect"/>

我們就是要讓這個矩形進行三維旋轉。

定義一個方法,從以上三個 Slider 控件中獲得實時的值,然後改變矩形的三維方向(在三個軸上的旋轉角度)。

        void SetUI()
        {
            Visual v = ElementCompositionPreview.GetElementVisual(rect);
            // 設置方向
            float x = (float)sldX.Value;
            float y = (float)sldY.Value;
            float z = (float)sldZ.Value;
            Quaternion q = new Quaternion(x, y, z, 1f);
            v.Orientation = q;
        }

一個 Quaternion 實例包含四個值,前三個就是三個坐標軸上旋轉的值,那個 W 不管它,始終給它分配 1 就行了。

來,看看效果。

技術分享

這個示例的源代碼可以 點擊這裏下載。

好,本篇咱們就聊到這裏,下一篇老周再介紹一下如何用 Win 2D 組件在 XAML 元素上畫點東東,可以實現 WPF 中自定義 Renderer 的效果。

【Win 10 應用開發】UI Composition 劄記(三):與 XAML 集成