15

我想要一个有两行和它们之间的分隔符的网格布局。行的最小高度应为 80 像素。

这段代码很好用:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" MinHeight="80" />
        <RowDefinition Height="5" />
        <RowDefinition Height="*" MinHeight="80" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>

但我希望顶行具有自动高度,直到用户使用拆分器手动更改它。所以我把代码改成这样:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" MinHeight="80" />
        <RowDefinition Height="5" />
        <RowDefinition Height="*" MinHeight="80" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>

还有一个问题。拆分器仍然满足行约束,但如果我将拆分器拖得太低,它会开始无限增加顶行的高度。这导致底行完全低于窗口的底部边框。

我在 GridSplitter 代码上做了一些反射器,如果行具有自动或星形高度,它会使用不同的逻辑。

有什么建议我该如何“修复”它?

4

2 回答 2

8

我自己也遇到过几次这个问题。看起来 GridSplitter 似乎不能很好地与 Auto 配合使用。也就是说,我找到了一个潜在的解决方法。

您可以使用“星形系数”指定 GridLength 对象的值。这充当了所讨论长度的乘数。

在您的示例中,如果您将要保留的行作为星形,并将星形系数设置为一个非常大的数字,则该行将占用所有可用空间(迫使另一行成为其最小高度)。虽然这与“自动”的行为不同(第一行的高度不是由其内容高度决定的),但它可能会让你更接近。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" MinHeight="80" />
        <RowDefinition Height="5" />
        <RowDefinition Height="10000*" MinHeight="80" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" />
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" />
</Grid>
于 2010-10-19T23:31:04.560 回答
7

我已经为这个问题开发了一个解决方法。重点是在我们拖动拆分器时为第一行设置 MaxHeight。这里的代码:

public class FixedGridSplitter : GridSplitter
{
    private Grid grid;
    private RowDefinition definition1;
    private double savedMaxLength;

    #region static

    static FixedGridSplitter()
    {
        new GridSplitter();
        EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragCompletedEvent, new DragCompletedEventHandler(FixedGridSplitter.OnDragCompleted));
        EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragStartedEvent, new DragStartedEventHandler(FixedGridSplitter.OnDragStarted));
    }

    private static void OnDragStarted(object sender, DragStartedEventArgs e)
    {
        FixedGridSplitter splitter = (FixedGridSplitter)sender;
        splitter.OnDragStarted(e);
    }

    private static void OnDragCompleted(object sender, DragCompletedEventArgs e)
    {
        FixedGridSplitter splitter = (FixedGridSplitter)sender;
        splitter.OnDragCompleted(e);
    }

    #endregion

    private void OnDragStarted(DragStartedEventArgs sender)
    {            
        grid = Parent as Grid;
        if (grid == null)
            return;            
        int splitterIndex = (int)GetValue(Grid.RowProperty);
        definition1 = grid.RowDefinitions[splitterIndex - 1];
        RowDefinition definition2 = grid.RowDefinitions[splitterIndex + 1];
        savedMaxLength = definition1.MaxHeight;            

        double maxHeight = definition1.ActualHeight + definition2.ActualHeight - definition2.MinHeight;            
        definition1.MaxHeight = maxHeight;
    }

    private void OnDragCompleted(DragCompletedEventArgs sender)
    {
        definition1.MaxHeight = savedMaxLength;
        grid = null;
        definition1 = null;
    }
}

然后只需将 GridSplitter 替换为 FixedGridSplitter。

注意:此代码不通用 - 它不支持列并假定底行已指定 MinHeight。

于 2010-10-20T09:49:15.023 回答