【Win 10 應用開發】UI Composition 劄記(三):與 XAML 集成
除了 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 集成