背水一戰 Windows 10 之 控制項(控制項基類 - UIElement ): 獲取 UIElement 的位置, UIElement 的佈局相關(Measure, Arrange), UIElement 的非完整像素佈局(UseLayoutRounding), UIElement 的其他特性(V... ...
背水一戰 Windows 10 (72) - 控制項(控制項基類): UIElement - UIElement 的位置, UIElement 的佈局, UIElement 的其他特性
作者:webabcd
介紹
背水一戰 Windows 10 之 控制項(控制項基類 - UIElement )
- 獲取 UIElement 的位置
- UIElement 的佈局相關(Measure, Arrange)
- UIElement 的非完整像素佈局(UseLayoutRounding)
- UIElement 的其他特性(Visibility, Opacity, CacheMode)
示例
1、演示如何獲取 UIElement 的位置
Controls/BaseControl/UIElementDemo/TransformToVisualDemo.xaml
<Page x:Class="Windows10.Controls.BaseControl.UIElementDemo.TransformToVisualDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5"> <Rectangle Name="rectangle1" Width="300" Height="200" Fill="Red" /> <Rectangle Name="rectangle2" Width="150" Height="100" Fill="Green" /> </Grid> <TextBlock Name="lblMsg" Margin="5" /> </StackPanel> </Grid> </Page>
Controls/BaseControl/UIElementDemo/TransformToVisualDemo.xaml.cs
/* * UIElement - UIElement(繼承自 DependencyObject, 請參見 /Controls/BaseControl/DependencyObjectDemo/) * TransformToVisual(UIElement visual) - 返回相對於指定 UIElement 原點(左上角頂點)的 GeneralTransform 類型的對象,傳 null 值則為相對於 app 原點(左上角頂點) * * * GeneralTransform * Point TransformPoint(Point point) - 獲取相對於指定位置的位置 * * * 本例用於演示如何獲取 UIElement 的位置 */ using System; using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; namespace Windows10.Controls.BaseControl.UIElementDemo { public sealed partial class TransformToVisualDemo : Page { public TransformToVisualDemo() { this.InitializeComponent(); this.Loaded += TransformToVisualDemo_Loaded; } void TransformToVisualDemo_Loaded(object sender, RoutedEventArgs e) { Demo1(); Demo2(); } // 演示如何獲取 UIElement 相對於 app 原點(左上角頂點)的位置 private void Demo1() { GeneralTransform generalTransform = rectangle1.TransformToVisual(null); // 獲取 rectangle1 相對於 app 原點(左上角頂點)的 GeneralTransform Point point = generalTransform.TransformPoint(new Point(0, 0)); // rectangle1 的原點(左上角頂點)相對於屏幕 0,0 點的位置 lblMsg.Text += "紅色矩形的原點(左上角頂點)相對於屏幕的原點(左上角頂點)的位置:" + point.ToString(); lblMsg.Text += Environment.NewLine; } // 演示如何獲取 UIElement 相對於另一個 UIElement 原點(左上角頂點)的位置 private void Demo2() { GeneralTransform generalTransform = rectangle1.TransformToVisual(rectangle2); // 獲取 rectangle1 相對於 rectangle2 原點(左上角頂點)的 GeneralTransform Point point = generalTransform.TransformPoint(new Point(0, 0)); // rectangle1 的原點(左上角頂點)相對於 rectangle2 的原點(左上角頂點)的位置 lblMsg.Text += "紅色矩形的原點(左上角頂點)相對於綠色矩形的原點(左上角頂點)的位置:" + point.ToString(); } } }
2、演示 UIElement 的佈局相關
Controls/BaseControl/UIElementDemo/LayoutDemo.xaml
<Page x:Class="Windows10.Controls.BaseControl.UIElementDemo.LayoutDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <StackPanel Name="stackPanel" Margin="1 2 3 4" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Background="Orange"> <Rectangle Name="rectangle1" Fill="White" Width="100" Height="100" /> </StackPanel> <TextBlock Name="lblMsg" Margin="5" /> </StackPanel> </Grid> </Page>
Controls/BaseControl/UIElementDemo/LayoutDemo.xaml.cs
/* * UIElement - UIElement(繼承自 DependencyObject, 請參見 /Controls/BaseControl/DependencyObjectDemo/) * Measure(), Arrange(), InvalidateMeasure(), InvalidateArrange() - 參見 /MyControls/MyControl2.cs * DesiredSize - 獲取通過 Measure() 計算後得到的期望尺寸 * RenderSize - 獲取通過 Arrange() 計算後得到的呈現尺寸 * UpdateLayout() - 相當於依次調用 InvalidateMeasure() 和 InvalidateArrange(),然後同步等待結果,而 InvalidateMeasure() 和 InvalidateArrange() 本身是非同步處理的 * * * 註: * 1、uwp 的 layout 是一個遞歸系統,更多說明請參見 /MyControls/MyControl2.cs * 2、InvalidateMeasure() 就是遞歸調用自己和子輩門的 Measure() * 3、InvalidateArrange() 就是遞歸調用自己和子輩門的 Arrange() * * * 本例用於演示 UIElement 的佈局相關 */ using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10.Controls.BaseControl.UIElementDemo { public sealed partial class LayoutDemo : Page { public LayoutDemo() { this.InitializeComponent(); this.Loaded += LayoutDemo_Loaded; } private void LayoutDemo_Loaded(object sender, RoutedEventArgs e) { lblMsg.Text += stackPanel.DesiredSize.ToString(); // 204,106(期望尺寸,是包括 margin 的) lblMsg.Text += Environment.NewLine; lblMsg.Text += stackPanel.RenderSize.ToString(); // 200,100(呈現尺寸,是不包括 margin 的) lblMsg.Text += Environment.NewLine; // 更改外觀 stackPanel.Margin = new Thickness(5); rectangle1.Height = 300; // 更改外觀後,佈局系統會自動調用 InvalidateMeasure() 和 InvalidateArrange(),但是這是個非同步的過程 // 所以此處獲取到的 DesiredSize 和 RenderSize 仍然是更改外觀之前的值 lblMsg.Text += stackPanel.DesiredSize.ToString(); // 204,106(期望尺寸,是包括 margin 的) lblMsg.Text += Environment.NewLine; lblMsg.Text += stackPanel.RenderSize.ToString(); // 200,100(呈現尺寸,是不包括 margin 的) lblMsg.Text += Environment.NewLine; // 如果想要同步知道結果的話就調用 UpdateLayout() stackPanel.UpdateLayout(); // 所以此處獲取到的 DesiredSize 和 RenderSize 為更改外觀之後的值 lblMsg.Text += stackPanel.DesiredSize.ToString(); // 210,310(期望尺寸,是包括 margin 的) lblMsg.Text += Environment.NewLine; lblMsg.Text += stackPanel.RenderSize.ToString(); // 200,300(呈現尺寸,是不包括 margin 的) } } }
3、演示 UIElement 的 UseLayoutRounding 的應用
Controls/BaseControl/UIElementDemo/UseLayoutRoundingDemo.xaml
<Page x:Class="Windows10.Controls.BaseControl.UIElementDemo.UseLayoutRoundingDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <!-- UseLayoutRounding - 是否使用完整像素佈局。預設值為 true 舉例說明:如果設置了某個元素的 Margin="1.6"(非完整像素),那麼 1、當 UseLayoutRounding="true" 時,則設置為 Margin="1.6" 的元素的各個方向的 Margin 是不相等的,但是顯示清晰 2、當 UseLayoutRounding="false" 時,則設置為 Margin="1.6" 的元素的各個方向的 Margin 是相等的,但是顯示不清晰 註:UseLayoutRounding 是會自動繼承的,即子元素會繼承父元素的 UseLayoutRounding 設置 --> <Grid Width="200" Height="200" Margin="5" HorizontalAlignment="Left"> <Border BorderBrush="Black" Background="White" BorderThickness="1"></Border> <Border BorderBrush="Black" Background="White" BorderThickness="1" Margin="1.6" UseLayoutRounding="True"></Border> </Grid> <Grid Width="200" Height="200" Margin="5" HorizontalAlignment="Left"> <Border BorderBrush="Black" Background="White" BorderThickness="1"></Border> <Border BorderBrush="Black" Background="White" BorderThickness="1" Margin="1.6" UseLayoutRounding="False"></Border> </Grid> </StackPanel> </Grid> </Page>
Controls/BaseControl/UIElementDemo/UseLayoutRoundingDemo.xaml.cs
/* * UIElement - UIElement(繼承自 DependencyObject, 請參見 /Controls/BaseControl/DependencyObjectDemo/) * UseLayoutRounding - 是否使用完整像素佈局。預設值為 true * * * 本例用於演示 UIElement 的 UseLayoutRounding 的應用 */ using Windows.UI.Xaml.Controls; namespace Windows10.Controls.BaseControl.UIElementDemo { public sealed partial class UseLayoutRoundingDemo : Page { public UseLayoutRoundingDemo() { this.InitializeComponent(); } } }
4、演示 UIElement 的其他特性
Controls/BaseControl/UIElementDemo/OthersDemo.xaml
<Page x:Class="Windows10.Controls.BaseControl.UIElementDemo.OthersDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="5"> <Rectangle Fill="Orange" Width="100" Height="100" Margin="5" Visibility="Collapsed" /> <Rectangle Fill="Orange" Width="100" Height="100" Margin="5" Opacity="0.5" CacheMode="BitmapCache" /> </StackPanel> </Grid> </Page>
Controls/BaseControl/UIElementDemo/OthersDemo.xaml.cs
/* * UIElement - UIElement(繼承自 DependencyObject, 請參見 /Controls/BaseControl/DependencyObjectDemo/) * Visibility - 可見性 * Visible - 顯示 * Collapsed - 不顯示,且不占位 * Opacity - 不透明度(0.0 - 1.0 之間,預設值為 1.0) * CacheMode - 緩存模式 * null - 預設值 * BitmapCache - 用 GPU 渲染 RenderTransform 和 Opacity * 如果 RenderTransform 或 Opacity 使用了 storyboard 動畫的話,動畫一律將變為 Dependent Animation 而不是 Independent Animation,這樣性能就會變差。一般來說不用設置成 BitmapCache 模式 * * * 本例用於演示 UIElement 的其他特性 */ using Windows.UI.Xaml.Controls; namespace Windows10.Controls.BaseControl.UIElementDemo { public sealed partial class OthersDemo : Page { public OthersDemo() { this.InitializeComponent(); // this.Visibility = Visibility.Collapsed; // this.Opacity = 0.5; // this.CacheMode = null; // this.CacheMode = new BitmapCache(); } } }
OK
[源碼下載]