博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
重新想象 Windows 8 Store Apps (17) - 控件基础: Measure, Arrange, GeneralTransform, VisualTree...
阅读量:4312 次
发布时间:2019-06-06

本文共 10200 字,大约阅读时间需要 34 分钟。

原文:

重新想象 Windows 8 Store Apps (17) - 控件基础: Measure, Arrange, GeneralTransform, VisualTree

作者:
介绍
重新想象 Windows 8 Store Apps 之 控件基础

  • Measure() 和 Arrange() - xaml 的 layout 系统
  • GeneralTransform - 通过 UIElement.TransformToVisual() 获取元素的位置信息
  • VisualTree - 可视树

示例
1、演示 xaml 的 layout 系统
Controls/Basic/MeasureArrange.xaml

Controls/Basic/MeasureArrange.xaml.cs

/* * 演示 Layout 系统 *  * win8 xaml 的 layout 就是一个递归系统,本 demo 就递归的一个过程做说明(步骤顺序参见代码注释中的序号) */using System;using System.Diagnostics;using Windows.Foundation;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;namespace XamlDemo.Controls.Basic{    public sealed partial class MeasureArrange : Page    {        public MeasureArrange()        {            this.InitializeComponent();        }    }    public class MyStackPanel : StackPanel    {        // 1、首先爸爸知道自己能够提供的尺寸 availableSize,然后告诉儿子们        protected override Size MeasureOverride(Size availableSize)        {            // 2、儿子们收到 availableSize 后,又结合了自身的实际情况,然后告诉爸爸儿子们所期望的尺寸 desiredSize            Size desiredSize = base.MeasureOverride(availableSize);            Debug.WriteLine("availableSize: " + availableSize.ToString());            Debug.WriteLine("desiredSize: " + desiredSize.ToString());            return desiredSize;            // 以下是自定义的 Measure 逻辑,供参考            /*            Size childrenSize = new Size(0, 0);            foreach (UIElement child in this.Children)            {                child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));                childrenSize.Width += child.DesiredSize.Width;                childrenSize.Height += child.DesiredSize.Height;            }            return childrenSize;            */        }        // 3、爸爸收到儿子们的反馈后,告诉儿子们自己最终提供的尺寸 finalSize        protected override Size ArrangeOverride(Size finalSize)        {            // 4、儿子们根据 finalSize 安排各自的位置,然后爸爸的呈现尺寸也就确定了 renderSize            Size renderSize = base.ArrangeOverride(finalSize);            Debug.WriteLine("finalSize: " + finalSize.ToString());            Debug.WriteLine("renderSize: " + renderSize.ToString());            return renderSize;            // 以下是自定义的 Arrange 逻辑,供参考            /*            Point childPos = new Point(0, 0);            foreach (UIElement child in this.Children)            {                child.Arrange(new Rect(childPos, new Size(child.DesiredSize.Width, child.DesiredSize.Height)));                childPos.Y += child.RenderSize.Height;            }            return finalSize;            */        }    }}/* * 输出结果: * availableSize: 200,200 * desiredSize: 150,250 * finalSize: 200,250 * renderSize: 200,250*//* * 注: * UIElement *     调用 Measure() 方法后会更新 DesiredSize 属性 *     调用 Arrange() 方法后会更新 RenderSize 属性 *     UpdateLayout() - 强制 layout 递归更新 *  * FrameworkElement - 继承自 UIElement *     MeasureOverride() - 重写 Measure() *     ArrangeOverride() - 重写 Arrange() *     ActualWidth 和 ActualHeight 来自 RenderSize,每次 UpdateLayout() 后都会被更新 */

2、演示如何获取UI元素的位置信息
Controls/Basic/GeneralTransformDemo.xaml

Controls/Basic/GeneralTransformDemo.xaml.cs

/* * 演示 GeneralTransform 的应用,可以通过 UIElement.TransformToVisual() 获取 */using System;using Windows.Foundation;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Media;namespace XamlDemo.Controls.Basic{    public sealed partial class GeneralTransformDemo : Page    {        public GeneralTransformDemo()        {            this.InitializeComponent();            this.Loaded += TransformToVisual_Loaded;        }        void TransformToVisual_Loaded(object sender, RoutedEventArgs e)        {            lblMsg.Text = "";            Demo1();            lblMsg.Text += Environment.NewLine;            Demo2();        }        // 演示如何获取 UIElement 相对于屏幕原点所占用的矩形区域        private void Demo1()        {            GeneralTransform generalTransform = rectangle1.TransformToVisual(null); // 获取 rectangle1 相对于屏幕的 GeneralTransform            Point point = generalTransform.TransformPoint(new Point(0, 0)); // rectangle1 的原点(左上角顶点)相对于屏幕 0,0 点的位置            Rect rect = new Rect(point, new Size(rectangle1.ActualWidth, rectangle1.ActualHeight));            lblMsg.Text += "红色矩形相对于屏幕原点的位置:" + rect.ToString();        }        // 演示如何获取 UIElement 相对于另一个 UIElement 原点所占用的矩形区域        private void Demo2()        {            GeneralTransform generalTransform = rectangle1.TransformToVisual(rectangle2); // 获取 rectangle1 相对于 rectangle2 的 GeneralTransform            Point point = generalTransform.TransformPoint(new Point(0, 0)); // rectangle1 的原点(左上角顶点)相对于 rectangle2 的原点(左上角顶点)的位置            Rect rect = new Rect(point, new Size(rectangle1.ActualWidth, rectangle1.ActualHeight));            lblMsg.Text += "红色矩形相对于绿色矩形左上角顶点的位置:" + rect.ToString();        }    }}

3、演示 VisualTreeHelper 的应用
Controls/Basic/VisualTree.xaml

Controls/Basic/VisualTree.xaml.cs

/* * 演示 VisualTreeHelper 的应用 *  * VisualTreeHelper - 访问可视树的帮助类 *     GetChildrenCount(DependencyObject reference) - 获取指定的元素内的子元素的数量 *     DependencyObject GetChild(DependencyObject reference, int childIndex) - 获取指定的元素内的,指定索引位置的子元素 *     GetParent(DependencyObject reference) - 获取指定的元素的父元素 *     FindElementsInHostCoordinates(Point intersectingPoint, UIElement subtree, bool includeAllElements) - 查找某一点内的全部元素(包括控件模板内的元素) *         intersectingPoint - 指定的点的坐标 *         subtree - 在此元素内进行查找,包括此元素 *         includeAllElements *             true - 查找全部元素,包括 IsHitTestVisible 为 true 的和 IsHitTestVisible 为 false 的 *             false - 仅查找 IsHitTestVisible 为 true 的元素 *     FindElementsInHostCoordinates(Rect intersectingRect, UIElement subtree, bool includeAllElements) - 查找某一矩形区域内的全部元素(包括控件模板内的元素) *         intersectingRect - 指定的矩形区域 *         subtree - 在此元素内进行查找,包括此元素 *         includeAllElements *             true - 查找全部元素,包括 IsHitTestVisible 为 true 的和 IsHitTestVisible 为 false 的 *             false - 仅查找 IsHitTestVisible 为 true 的元素 */using System;using System.Collections.Generic;using Windows.Foundation;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Media;namespace XamlDemo.Controls.Basic{    public sealed partial class VisualTree : Page    {        public VisualTree()        {            this.InitializeComponent();            this.Loaded += VisualTree_Loaded;        }        void VisualTree_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)        {            // 获取 container 中包含的元素            lblMsg.Text = "container 中包含的元素有:";            int numVisuals = VisualTreeHelper.GetChildrenCount(container);            for (int i = 0; i < numVisuals; i++)            {                DependencyObject element = VisualTreeHelper.GetChild(container, i);                lblMsg.Text += Environment.NewLine;                lblMsg.Text += element.GetType().ToString();            }            lblMsg.Text += Environment.NewLine;            lblMsg.Text += Environment.NewLine;            // 在 scrollViewer 控件自身的模板中查找类型为 ScrollBar 的名为 VerticalScrollBar 的控件            lblMsg.Text += "查找 scrollViewer 中的名为“VerticalScrollBar”的 ScrollBar 控件:";            lblMsg.Text += Environment.NewLine;            ScrollBar scrollBar = GetVisualChild
(scrollViewer, "VerticalScrollBar"); if (scrollBar != null) lblMsg.Text += "找到了"; else lblMsg.Text += "未找到"; } private void container_Tapped_1(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { // 获取鼠标单击的位置,container 范围内所包含的全部元素(包括控件模板内的元素) lblMsg.Text = "鼠标单击的位置,container 内,包含的元素有:"; IEnumerable
elementsPoint = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), container, true); var elementsPointEnumerator = elementsPoint.GetEnumerator(); while (elementsPointEnumerator.MoveNext()) { lblMsg.Text += Environment.NewLine; lblMsg.Text += elementsPointEnumerator.Current.GetType().ToString(); } lblMsg.Text += Environment.NewLine; lblMsg.Text += Environment.NewLine; // 获取以鼠标单击的位置为顶点,100*100 大小的矩形内,container 范围内所包含的全部元素(包括控件模板内的元素) lblMsg.Text += "以鼠标单击的位置为顶点,100*100 大小的矩形范围内,container 内,包含的元素有:"; IEnumerable
elementsRect = VisualTreeHelper.FindElementsInHostCoordinates(new Rect(e.GetPosition(null), new Size(100, 100)), container, true); var elementsRectEnumerator = elementsRect.GetEnumerator(); while (elementsRectEnumerator.MoveNext()) { lblMsg.Text += Environment.NewLine; lblMsg.Text += elementsRectEnumerator.Current.GetType().ToString(); } } ///
/// 获取指定元素内部的指定名称的 FrameworkElement /// private T GetVisualChild
(DependencyObject parent, string name) where T : FrameworkElement { // T 是引用类型则为 null,T 是值类型则为 0 T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject obj = VisualTreeHelper.GetChild(parent, i); child = obj as T; if (child == null || child.Name != name) child = GetVisualChild
(obj, name); if (child != null) break; } return child; } }}

OK

posted on
2014-03-08 15:53 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/3588063.html

你可能感兴趣的文章
[效率提升]如何管理好你的电脑文件
查看>>
C++实验二
查看>>
Sultan's Dowry Problem - 苏丹新娘问题
查看>>
SharePoint2010 富文本框添加图片功能的扩展
查看>>
零零碎碎的知识
查看>>
UNIX基础--用户和基本账户管理
查看>>
设计模式
查看>>
5.0以上机器XPOSED框架安装流程
查看>>
静态方法与非静态方法
查看>>
[转]iOS进阶路线以及进阶书籍
查看>>
期货监管机构,国际著名。
查看>>
vim编程技巧
查看>>
Activator.CreateInstance 方法 (Type) 的用法
查看>>
我的将军啊
查看>>
openstack mariadb 容器无法启动问题解决方法
查看>>
实例的初始化过程: new 对象
查看>>
10.02 一个简单的串口的初始化程序
查看>>
Ant学习笔记
查看>>
vc++ 在程序中运行另一个程序的方法
查看>>
Python面向对象编程及内置方法
查看>>