24

鉴于下面的 XAML,我如何让 gridsplitter 尊重赋予第三行的 MinHeight 并将内容保留在我的窗口内?

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition MinHeight="40" />
    </Grid.RowDefinitions>
    <Expander Grid.Row="0" ExpandDirection="Down" VerticalAlignment="Top">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" MinHeight="40" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Border Grid.Row="0" MinHeight="100" Background="Black" />
            <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Background="LightBlue" ResizeBehavior="PreviousAndCurrent" />
        </Grid>
    </Expander>
    <Expander Grid.Row="1" ExpandDirection="Down" VerticalAlignment="Top">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" MinHeight="40" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Border Grid.Row="0" MinHeight="100" Background="Black" />
            <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Background="LightBlue" ResizeBehavior="PreviousAndCurrent" />
        </Grid>
    </Expander>
    <Border DockPanel.Dock="Bottom"  Grid.Row="2" Background="Lime" MinHeight="30" >
        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DockPanel},Path=ActualHeight,StringFormat={}{0:f0}}" />
    </Border>
</Grid>
4

3 回答 3

23

您的代码的方式是,这无法完成,伙计。这是由于 GridSplitter 的工作方式。

几点

  • GridSplitter 将始终在直接相邻的行/列上工作
  • 实际上,您的 MinHeight 受到尊重,但 GridSplitter 的增长请求也受到尊重,这导致 Grid 变得比您的 Window 更大
  • 当大小设置为自动时,行/列将始终根据其内容调整大小,而不是更大,而不是更小
  • 因此,如果 GridSplitter 夹在两个 * 大小的行/列之间,那么它将隐含尊重您的 MinHeight,因为实际上,它不会触及它

你有几个解决方案

  1. 在第 3 位置添加另一行 * 大小,并在第 3 行设置边框,RowSpan 为 2(因此第 3 行是真正调整大小的行,并且没有触及第 4 行。虽然这也会有副作用。
  2. 在 GridSplitter 上处理 DragEnter 和 PreviewMouseMove 事件的混合,跟踪焦点,并在达到特定大小时取消 (e.Handled = true) 事件。

这是我能想到的朋友,希望对我有所帮助。

于 2011-06-23T22:19:39.707 回答
3

我创建了一个自定义网格拆分器类,它不允许网格拆分器离开窗口的边缘(底部或侧面)。

Public Class CustomGridSplitter
Inherits GridSplitter

Public Enum SplitterDirectionEnum
    Horizontal
    Vertical
End Enum

Public Property SplitterDirection As SplitterDirectionEnum
Public Property MinimumDistanceFromEdge As Integer

Private _originPoint As Point

Private Sub customSplitter_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles MyBase.MouseDown
    _originPoint = e.GetPosition(Window.GetWindow(Me))
End Sub

Private Sub customSplitter_PreviewMouseMove(sender As Object, e As MouseEventArgs) Handles MyBase.PreviewMouseMove

    If e.LeftButton = MouseButtonState.Pressed Then
        Dim pwindow As Window = Window.GetWindow(Me)
        Dim newPoint As Point = e.GetPosition(pwindow)

        If SplitterDirection = SplitterDirectionEnum.Horizontal Then
            If newPoint.Y >= _originPoint.Y Then
                If newPoint.Y >= pwindow.ActualHeight - MinimumDistanceFromEdge Then
                    e.Handled = True
                End If
            Else
                If newPoint.Y > pwindow.ActualHeight - (MinimumDistanceFromEdge + 2) Then
                    e.Handled = True
                End If
            End If
        Else
            If newPoint.X >= _originPoint.X Then
                If newPoint.X >= pwindow.ActualWidth - MinimumDistanceFromEdge Then
                    e.Handled = True
                End If
            Else
                If newPoint.X > pwindow.ActualWidth - (MinimumDistanceFromEdge + 2) Then
                    e.Handled = True
                End If
            End If
        End If


        _originPoint = newPoint
    End If
End Sub

结束类

要在 XAML 中使用它:

<CustomGridSplitter SplitterDirection="Vertical" MinimumDistanceFromEdge="100" x:Name="splitterCenter" ResizeDirection="Columns" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="2" Margin="2,0,2,0"/>

要设置的自定义属性是“SplitterDirection”和“MinimumDistanceFromEdge”。一切都像基本网格拆分器一样工作。

这使用鼠标事件来确定用户在窗口中拖动拆分器的位置,并在事件离边缘太近时处理事件。

于 2016-05-03T13:37:35.010 回答
-1

我找到了这个问题的另一个解决方案,尽管在一个更简单的情况下,我在一个窗口内只有两列我想调整大小。

我想出的解决方案(在此处更详细地描述:https : //stackoverflow.com/a/46924893/6481970)是为调整网格大小、GridSplitter 移动以及窗口何时添加事件回调调整大小(以处理您调整窗口大小以不再适合内容的情况,因为网格不会自动调整自身大小以适合较小的窗口)。

这是一些简化的代码:

XAML:

<Grid x:Name="ResizeGrid" SizeChanged="ResizeGrid_SizeChanged">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="C0" Width="150" MinWidth="50" />
        <ColumnDefinition Width="5" />
        <ColumnDefinition x:Name="C2" Width="*" MinWidth="50" />
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0" Background="Green" />
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" DragCompleted="GridSplitter_DragCompleted" />
    <Grid Grid.Column="2" Background="Red" />
</Grid>

C#代码背后:

C0.MaxWidth = Math.Min(ResizeGrid.ActualWidth, ActualWidth) - (C2.MinWidth + 5);
于 2017-10-25T06:01:03.253 回答