【转】【WPF】WPF中MeasureOverride ArrangeOverride 的理解

1. Measure Arrange这两个方法是UIElement的方法

    MeasureOverride ArrangeOverride这两个方法是FrameworkElement的方法,FrameworkElement是UIElement的子类

    MeasureOverride传入父容器分配的可用空间,返回该容器根据其子元素大小计算确定的在布局过程中所需的大小。

    ArrangeOverride传入父容易最终分配的控件大小,返回使用的实际大小

2. MeasureOverride 用于计算本身及其子控件的大小

    ArrangeOverride用于布局本身及其子控件的位置和大小

3. WPF布局系统大概分为两步:Measure和Arrange

    Measure方法自顶而下,递归调用各子控件的Measure方法,Measure方法会把该控件所需的大小控件存在desired size属性中,控件根据各子控件的desired size 属性确定自身空间大小,并返回自己的desired size 

   Arrange方法发生在Measure中,传入Measure方法计算到的大小,利用控件的位置设置分配子控件的位置

简单来说,这两个方法一个管大小,一个管布局,都需要调用子类的Measure和Arrage

 

public class DiagnolPanel:Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            var mySize = new Size();

            foreach (UIElement child in this.InternalChildren)
            {
                child.Measure(availableSize);
                mySize.Width += child.DesiredSize.Width;
                mySize.Height += child.DesiredSize.Height;
            }

            return mySize;
        }    

        protected override Size ArrangeOverride(Size finalSize)
        {
            var location = new Point();

            int childNumber = 0;
            int middleChild = GetTheMiddleChild(this.InternalChildren.Count);

            foreach (UIElement child in this.InternalChildren)
            {
               
                if (childNumber < middleChild)
                {
                    child.Arrange(new Rect(location, child.DesiredSize));
                    location.X += child.DesiredSize.Width;
                    location.Y += child.DesiredSize.Height;
                }
                else
                {
                    //The x location will always keep increasing, there is no need to take care of it
                    location.X = GetXLocationAfterMiddleChild(childNumber);

                    //If the UIElements are odd in number
                    if (this.InternalChildren.Count % 2 != 0)
                    { 
                        //We need to get the Y location of the child before middle location, 
                        //to have the same Y location for the child after middle child                      
                        int relativeChildBeforeMiddle = middleChild - (childNumber - middleChild);
                        location.Y = GetYLocationAfterMiddleChild(relativeChildBeforeMiddle);
                    }
                    else
                    {
                       ///TODO: Do the design for the even number of children
                    }

                    child.Arrange(new Rect(location, child.DesiredSize));
                }

                childNumber++;
            }

            return finalSize;
        }

        private double GetXLocationAfterMiddleChild(int childNUmber)
        {
            double xLocation = 0;
            for (int i = 0; i < childNUmber; i++)
            {
                xLocation += this.InternalChildren[i].DesiredSize.Width;
            }

            return xLocation;
        }

        private double GetYLocationAfterMiddleChild(int relativeChildNumber)
        {            
            UIElement correspondingChild = this.InternalChildren[relativeChildNumber - 2];
            Point pointCoordinates = 
            correspondingChild.TransformToAncestor((Visual)this.Parent).Transform(new Point(0, 0));

            return pointCoordinates.Y;
        }

        private int GetTheMiddleChild(int count)
        {
            int middleChild;
            if (count % 2 == 0)
            {
                middleChild = count / 2;
            }
            else
            {
                middleChild = (count / 2) + 1;
            }

            return middleChild;
        }
    }
}
<local:DiagnolPanel>
        <Button BorderBrush="Black" Background="Red" Content="0" Width="40"></Button>
        <Button BorderBrush="Black" Background="Red" Content="1" Width="40"></Button>

        <Button BorderBrush="Black" Background="Red" Content="2" Width="40"></Button>
        <Button BorderBrush="Black" Background="Red" Content="3" Width="40"></Button>

        <Button BorderBrush="Black" Background="Red" Content="4" Width="40"></Button>

        <Button BorderBrush="Black" Background="Red" Content="5" Width="40"></Button>

        <Button BorderBrush="Black" Background="Red" Content="6" Width="40"></Button>
        <Button BorderBrush="Black" Background="Red" Content="7" Width="40"></Button>

        <Button BorderBrush="Black" Background="Red" Content="8" Width="40"></Button>

    </local:DiagnolPanel>

 

原文地址:http://www.mamicode.com/info-detail-1730861.html

    https://www.codeproject.com/Articles/1034445/Understanding-MeasureOverride-and-ArrangeOverride

posted on 2018-08-30 20:09  梦琪小生  阅读(1329)  评论(0编辑  收藏  举报

导航