MeasureArrange

<Page
    x:Class="Win8XamlPractise.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Win8XamlPractise"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid Background="Transparent">
        <local:MSIStackPanel Margin="120 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="200" Orientation="Horizontal">
            <TextBlock Text="我是文本" Width="100" Height="100" />
            <Button Content="我是按钮" Width="150" Height="150" />
        </local:MSIStackPanel>
    </Grid>
</Page>
    public class MSIStackPanel : 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;
            */
        }
    }
/*
 * 注:
 * UIElement
 *     调用 Measure() 方法后会更新 DesiredSize 属性
 *     调用 Arrange() 方法后会更新 RenderSize 属性
 *     UpdateLayout() - 强制 layout 递归更新
 * 
 * FrameworkElement - 继承自 UIElement
 *     MeasureOverride() - 重写 Measure()
 *     ArrangeOverride() - 重写 Arrange()
 *     ActualWidth 和 ActualHeight 来自 RenderSize,每次 UpdateLayout() 后都会被更新
 */

 

posted on 2013-03-28 12:38  JackSlaterYu  阅读(131)  评论(0编辑  收藏  举报