zoukankan      html  css  js  c++  java
  • Understanding the WPF Layout System

    Many people don't understand how the WPF layout system works, or how that knowledge can help them in their projects. I intend to shine a little light on the mechanics behind all those cool layout controls in WPF.

    To explain the system, I will give a step-by-step example of creating a custom panel for WPF. This panel will be similar to the StackPanel, with the difference that it will expand the last child to fill the remaining space.

    Step 1: Create a new project

    Create a new WPF Application project called WpfLayoutSystem.

    Step 2: Add the custom panel

    Add a new class to the project. Call it ExpandingStackPanel.cs.

    To create your own custom panel, create a class that inherits from Panel, and override MeasureOverride and ArrangeOverride. That's it. This is the most basic panel, which doesn't add any functionality, yet.

    using System;
    using System.Windows;
    using System.Windows.Controls;
     
    namespace WpfLayoutSystem
    {
        class ExpandingStackPanel : Panel
        {
            protected override Size MeasureOverride(Size availableSize)
            {
                return base.MeasureOverride(availableSize);
            }
     
            protected override Size ArrangeOverride(Size finalSize)
            {
                return base.ArrangeOverride(finalSize);
            }
        }
    }

    Step 3: Measure

    A layout pass is made up of two steps. Measuring is the first. In the measure step, each control determines how much space it needs. Panels do this by measuring the child controls, and then basing it's desired size on the child controls. Content controls base their size on their content. Each panel tells its children how much space is available, and each child tells its parent how much space it wants.

    Lets examine how this works by writing an example. Here is the code for MeasureOverride.

    protected override Size MeasureOverride(Size availableSize)
    {
        double sumX = 0.0;
        double maxY = 0.0;
        foreach (UIElement child in this.Children)
        {
            child.Measure(new Size(Math.Max(availableSize.Width - sumX, 0.0), availableSize.Height));
            sumX += child.DesiredSize.Width;
            maxY = Math.Max(maxY, child.DesiredSize.Height);
        }
        return new Size(sumX, maxY);
    }

    Step 4: Arrange

    The second step in the layout pass is arranging. In the arrange step, each control arranges its content or children based on the available space. Each panel tells its children how much space they have been given. Each child tells the parent how much space it actually used. You may ask why the measure and arrange passes aren't combined. Often a control is given more or less space than it asked for in the measure pass, and then it will arrange itself differently.

    To see how this works, let's write the ArrangeOverride method.

    protected override Size ArrangeOverride(Size finalSize)
    {
        double x = 0.0;
        for (int i = 0; i < this.Children.Count - 1; i++)
        {
            UIElement child = this.Children[i];
            child.Arrange(new Rect(x, 0.0, child.DesiredSize.Width, child.DesiredSize.Height));
            x += child.DesiredSize.Width;
        }
        if (this.Children.Count > 0)
        {
            UIElement lastChild = this.Children[this.Children.Count - 1];
            lastChild.Arrange(new Rect(x, 0.0, Math.Max(finalSize.Width - x, 0.0), lastChild.DesiredSize.Height));
        }
        return finalSize;
    }

    Step 5: Using the panel

    I used this code to test the panel. Feel free to use it with other code, but I can't claim that it will work in all scenarios. It was just designed as an example. Anyway, here is MainWindow.xaml.

    <Window x:Class="WpfLayoutSystem.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfLayoutSystem"
            Title="MainWindow" Height="350" Width="525">
        <local:ExpandingStackPanel>
            <Button>A Button</Button>
            <Ellipse Width="80" Height="50" Stroke="Black" />
            <TextBlock>Some</TextBlock>
            <RadioButton>Other</RadioButton>
            <TextBox>Controls</TextBox>
            <Button>Another Button</Button>
        </local:ExpandingStackPanel>
    </Window>

    For your convenience, here is the entire ExpandingStackPanel class.

    using System;
    using System.Windows;
    using System.Windows.Controls;
     
    namespace WpfLayoutSystem
    {
        class ExpandingStackPanel : Panel
        {
            protected override Size MeasureOverride(Size availableSize)
            {
                double sumX = 0.0;
                double maxY = 0.0;
                foreach (UIElement child in this.Children)
                {
                    child.Measure(new Size(Math.Max(availableSize.Width - sumX, 0.0), availableSize.Height));
                    sumX += child.DesiredSize.Width;
                    maxY = Math.Max(maxY, child.DesiredSize.Height);
                }
                return new Size(sumX, maxY);
            }
     
            protected override Size ArrangeOverride(Size finalSize)
            {
                double x = 0.0;
                for (int i = 0; i < this.Children.Count - 1; i++)
                {
                    UIElement child = this.Children[i];
                    child.Arrange(new Rect(x, 0.0, child.DesiredSize.Width, child.DesiredSize.Height));
                    x += child.DesiredSize.Width;
                }
                if (this.Children.Count > 0)
                {
                    UIElement lastChild = this.Children[this.Children.Count - 1];
                    lastChild.Arrange(new Rect(x, 0.0, Math.Max(finalSize.Width - x, 0.0), lastChild.DesiredSize.Height));
                }
                return finalSize;
            }
        }
    }
  • 相关阅读:
    手机端学习助手的说明书需求以及团队PM选择
    对其他组的作品的评审意见
    项目介绍
    beta版项目总结
    Beta版说明书
    Alpha版会议总结
    第一阶段绩效评估
    今日事意见汇总
    Alpha版使用说明
    评审建议
  • 原文地址:https://www.cnblogs.com/xpvincent/p/4335801.html
Copyright © 2011-2022 走看看