WPF Grid RowSpan布局理解

时间:2014-06-04 13:14:28

标签: c# wpf layout grid

我有一个非常简单的XAML

<ui:BorderedGrid>
        <ui:BorderedGrid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </ui:BorderedGrid.RowDefinitions>
        <ui:BorderedGrid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </ui:BorderedGrid.ColumnDefinitions>
        <StackPanel Background="Blue" VerticalAlignment="Top" Grid.Row="0" Grid.Column="0" Margin="5" Width="200" Height="70"></StackPanel>
        <StackPanel Background="Red" VerticalAlignment="Top" Grid.Row="1" Grid.Column="0" Margin="5" Grid.RowSpan="2" Width="200" Height="300"></StackPanel>
        <StackPanel Background="Plum" VerticalAlignment="Top"  Grid.Row="0" Grid.Column="1" Margin="5" Grid.RowSpan="2" Width="200" Height="150"></StackPanel>
        <StackPanel Background="SaddleBrown" VerticalAlignment="Top"  Grid.Row="2" Grid.Column="1" Margin="5" Width="200" Height="250"></StackPanel>
    </ui:BorderedGrid>

BorderedGrid只是WPF标准Grid的扩展版本,它已覆盖OnRender函数来绘制列和行。以下是它的实施

public class BorderedGrid : Grid
    {
        protected override void OnRender(DrawingContext dc)
        {
            double leftOffset = 0;
            double topOffset = 0;
            System.Windows.Media.Pen pen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.LightGray, 1);
            pen.Freeze();

            foreach (RowDefinition row in this.RowDefinitions)
            {
                dc.DrawLine(pen, new System.Windows.Point(0, topOffset), new System.Windows.Point(this.ActualWidth, topOffset));
                topOffset += row.ActualHeight;
            }
            // draw last line at the bottom
            dc.DrawLine(pen, new System.Windows.Point(0, topOffset), new System.Windows.Point(this.ActualWidth, topOffset));

            foreach (ColumnDefinition column in this.ColumnDefinitions)
            {
                dc.DrawLine(pen, new System.Windows.Point(leftOffset, 0), new System.Windows.Point(leftOffset, this.ActualHeight));
                leftOffset += column.ActualWidth;
            }
            // draw last line on the right
            dc.DrawLine(pen, new System.Windows.Point(leftOffset, 0), new System.Windows.Point(leftOffset, this.ActualHeight));

            base.OnRender(dc);
        }
    }

问题是,我假设输出应该是这样的

Output should be like this

但实际输出是这样的

enter image description here

我的问题是为什么这个空白区域留在第一行?我想我错过了很简单的事情...... :(

2 个答案:

答案 0 :(得分:1)

无论列如何,所有行都需要对齐。由于第0行的高度是自动的。它的实际高度成为其最高子元素+边距的高度,这将是梅花高度+ 10(从边距)的一部分。

由于蓝色面板的高度(70)比其行的高度(第0行)短,并且它与顶部垂直对齐,因此您将获得其下方的空白区域。

我相信您看到的结果是基于您的行配置,行间距,高度等的预期结果。

在某种程度上,您的水平网格线已经暗示了计算的行高。

这是另一种看待它的方式:

第2行的高度是SaddleBrown的高度

第1行的高度是第2行的高度减去红色的高度

第0行的高度是Plum的高度减去第1行的高度

第0行的高度大于蓝色的高度。蓝色垂直对齐顶部,因此在其下方有一个白色空间。

答案 1 :(得分:0)

我尽量不花太多时间与WPF Auto战斗。看起来你的两列在布局方面基本上是独立的。你可以这样做,基本上渲染两个独立的列:

<ui:BorderedGrid>
        <ui:BorderedGrid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </ui:BorderedGrid.ColumnDefinitions>
        <StackPanel Width="200" Grid.Column="0">
            <StackPanel Background="Blue"Margin="5" Height="70"></StackPanel>
            <StackPanel Background="Red" Margin="5" Height="300"></StackPanel>
        </StackPanel>
        <StackPanel Width="200" Grid.Column="1">
            <StackPanel Background="Plum" Margin="5" Height="150"></StackPanel>
            <StackPanel Background="SaddleBrown"Margin="5" Height="250"></StackPanel>
        </StackPanel>
</ui:BorderedGrid>