原文:WPF 自适应布局控件

    public class KDLayoutGroup : Grid
    {
        public double LabelWidth { get; set; }


        public double GetLabelWidth()
        {
            return LabelWidth;
        }

        public void SetLabelWidth(double value)
        {
            if (this.Parent is KDLayoutControl)
            {
                double w = (this.Parent as KDLayoutControl).GetLableWidth();
                if (w < value)
                {
                    (this.Parent as KDLayoutControl).SetLabelWidth(value);
                }

                for (int i = 0; i < Children.Count; i++)
                {

                    SetBatchLabelWidth(Children[i], value);
                }

            }
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            if (Children.Count == this.ColumnDefinitions.Count)
                return;

            for (int i = 0; i < Children.Count; i++)
            {
                var column = new ColumnDefinition();
                //column.Width = new GridLength(0,GridUnitType.Auto);
                this.ColumnDefinitions.Add(column);

                Children[i].SetValue(Grid.ColumnProperty, i);

                SetBatchLabelWidthOther(Children[i]);

            }

            base.OnRenderSizeChanged(sizeInfo);
        }

        private void SetBatchLabelWidth(UIElement el, double value)
        {
            if (el is KDLayoutItem)
            {
                double width = (el as KDLayoutItem).GetLabelWidht();
                if (width < value)
                {
                    (el as KDLayoutItem).SetLabelWidht(value);
                }
            }
            else
            {
                if (el is Panel)
                {
                    var cs = (el as Panel).Children;
                    for (int i = 0; i < cs.Count; i++)
                    {
                        SetBatchLabelWidth(cs[i], value);
                    }
                }

            }
        }

        private void SetBatchLabelWidthOther(UIElement el)
        {
            if (el is KDLayoutItem)
            {

                double width = (el as KDLayoutItem).GetLabelWidht();
                if (width > LabelWidth)
                {
                    LabelWidth = width;
                    SetLabelWidth(width);
                }
            }
            else
            {
                if (el is Panel)
                {
                    var cs = (el as Panel).Children;
                    for (int i = 0; i < cs.Count; i++)
                    {
                        SetBatchLabelWidthOther(cs[i]);
                    }
                }

            }
        }
    }
 public class KDLayoutControl : StackPanel
    {

        public double LabelWidth { get; set; }
        public double GetLableWidth()
        {
            return LabelWidth;
        }

        public void SetLabelWidth(double value)
        {
            LabelWidth = value;

            for (int i = 0; i < Children.Count; i++)
            {
                if ((Children[i] as KDLayoutGroup).GetLabelWidth() < LabelWidth)
                {
                    (Children[i] as KDLayoutGroup).SetLabelWidth(LabelWidth);
                }
            }
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            for (int i = 0; i < Children.Count; i++)
            {

                if ((Children[i] as KDLayoutGroup).GetLabelWidth() > LabelWidth)
                {
                    LabelWidth = (Children[i] as KDLayoutGroup).GetLabelWidth();
                }
            }

            SetLabelWidth(LabelWidth);

            base.OnRenderSizeChanged(sizeInfo);
        }
    }
<UserControl x:Class="PHMES.UI.Base.KDLayoutItem"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:PHMES.UI.Base"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Template>
        <ControlTemplate TargetType="local:KDLayoutItem">
            <DockPanel>
                <Label  x:Name="lbl" VerticalAlignment="Center"  VerticalContentAlignment="Center" Content="{TemplateBinding Label}"  />
                <ContentPresenter/>
            </DockPanel>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>
 public partial class KDLayoutItem : UserControl
    {
        public KDLayoutItem()
        {
            InitializeComponent();
        }
        public object Label
        {
            get { return (object)GetValue(LabelProperty); }
            set
            {
                SetValue(LabelProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for Label.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register("Label", typeof(object), typeof(KDLayoutItem), new PropertyMetadata(null));


        public double GetLabelWidht()
        {
            return (this.Template.FindName("lbl",this) as Label).ActualWidth;
        }
        public void SetLabelWidht(double width)
        {
            (this.Template.FindName("lbl", this) as Label).SetValue(WidthProperty,width);
        }
    }

功能类似dev的layoutcontrol,layoutgroup,layoutitem.

用法如下:

<Window x:Class="AutoWidthTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AutoWidthTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <local:KDLayoutControl>
        <local:KDLayoutGroup Height="50" VerticalAlignment="Top"  Margin="3">
            <local:KDLayoutItem Label="aaa">
                <TextBox />
            </local:KDLayoutItem>
            <local:KDLayoutItem Label="bbb">
                <TextBox />
            </local:KDLayoutItem>
            <local:KDLayoutItem Label="ccc">
                <TextBox />
            </local:KDLayoutItem>
        </local:KDLayoutGroup>
        <local:KDLayoutGroup Height="50" VerticalAlignment="Top"  Margin="3">
            <local:KDLayoutItem Label="number">
                <TextBox />
            </local:KDLayoutItem>
            <local:KDLayoutItem Label="name">
                <TextBox />
            </local:KDLayoutItem>
            <local:KDLayoutItem Label="age">
                <TextBox />
            </local:KDLayoutItem>
        </local:KDLayoutGroup>
        <local:KDLayoutGroup Height="50" VerticalAlignment="Top" Margin="3">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <local:KDLayoutItem Label="a">
                    <TextBox />
                </local:KDLayoutItem>
                <local:KDLayoutItem Label="b" Grid.Column="1" Grid.ColumnSpan="2">
                    <TextBox />
                </local:KDLayoutItem>
            </Grid>
        </local:KDLayoutGroup>
    </local:KDLayoutControl>
</Window>

不管label字段有多长,KDLayoutControl会设置容器内所有的label长度一致。

12-23 16:03