背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性

简介: 原文:背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性[源码下载] 背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIE...
原文: 背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性

[源码下载]


背水一战 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
[源码下载]

目录
相关文章
|
7月前
|
Windows
构建布局良好的Windows程序
构建布局良好的Windows程序
|
7月前
|
JavaScript Linux C#
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
150 0
|
C++ Windows
C++ Windows窗口程序:子窗口控件之按钮类button
C++ Windows窗口程序:子窗口控件之按钮类button
943 0
|
API C# Windows
C#实现操作Windows窗口句柄:遍历、查找窗体和控件【窗口句柄最全总结之一】
C#对Windows窗口或窗口句柄的操作,都是通过 P/Invoke Win32 API 实现的,DllImport引入Windows API操作窗口(句柄),可以实现枚举已打开的窗口、向窗口...
4011 0
C#实现操作Windows窗口句柄:遍历、查找窗体和控件【窗口句柄最全总结之一】
|
Windows
Windows程序设计——Windows单选按钮、复选框、分组框控件
Windows程序设计——Windows单选按钮、复选框、分组框控件
649 0
Windows程序设计——Windows单选按钮、复选框、分组框控件
|
Windows
Windows程序设计——(源代码)Windows单选按钮、复选框、分组框控件
Windows程序设计——(源代码)Windows单选按钮、复选框、分组框控件
216 0
windows窗口中控件的样式
windows窗口中控件的样式一.按钮样式 button BS_AUTO3STATE 创建一个与三态复选框相同的按钮,但该框在用户选择时更改其状态。状态循环通过检查,不确定和清除。 BS_AUTOCHECKBOX 创建一个与复选框相同的按钮,但每次用户选中复选框时,检查状态会自动在已选中和已清除之间切换。
1345 0
|
C#
WPF 控件库——仿制Windows10的进度条
原文:WPF 控件库——仿制Windows10的进度条 一、其实有现成的   先来看看Windows10进度条的两种模式:       网上有不少介绍仿制Windows10进度条的文章,也都实现了不错的效果。
1416 0
|
C# Windows 开发者
Windows 8.1 新增控件之 MenuFlyout
原文:Windows 8.1 新增控件之 MenuFlyout 开始这篇讲解前,我们先来温习一下Flyout 的内容,当触发应用中某个Button 时会有Flyout 出现提示用户该操作接下来将会发生什么。
822 0