具有最小约束的GridSplitter

Sel*_*don 15 wpf xaml gridsplitter

我想要一个有两行的网格布局和它们之间的分割器.行的最小高度应为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>
Run Code Online (Sandbox Code Playgroud)

但我希望顶行有一个自动高度,直到用户使用拆分器手动更改它.所以我把代码更改为:

<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>
Run Code Online (Sandbox Code Playgroud)

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

我在GridSplitter代码上做了一些Reflector,看看如果行有Auto或Star高度它会使用不同的逻辑.

任何建议如何"修复"它?

mbu*_*ill 6

我自己曾经遇到过这个问题几次.似乎GridSplitter与Auto不兼容.也就是说,我找到了一个潜在的解决方法.

您可以使用"星系数"指定GridLength对象的值.这可以作为所讨论长度的乘数.

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

<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>
Run Code Online (Sandbox Code Playgroud)


Sel*_*don 6

我已经针对这个问题开发了一种解决方法.点是在我们拖动拆分器时为顶行设置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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后用FixedGridSplitter替换GridSplitter.

注意:此代码不是通用的 - 它不支持列并假设底行指定了MinHeight.