Остановить Gridsplitter растягивая контент за окном - PullRequest
23 голосов
/ 04 мая 2011

Учитывая приведенный ниже XAML, как сделать, чтобы гридсплиттер учитывал MinHeight, заданный для 3-й строки, и чтобы содержимое оставалось внутри моего окна?

<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>

Ответы [ 3 ]

23 голосов
/ 24 июня 2011

То, как ваш код, это не может быть сделано, приятель. Это связано с тем, как работает GridSplitter.

Несколько баллов

  • GridSplitter всегда будет работать с соседними строками / столбцами
  • На самом деле ваш MinHeight IS уважают, но так же, как и запрос GridSplitter, уважать его, что приводит к тому, что Grid становится больше, чем ваше Window
  • При выборе размера Авто размер строки / столбца всегда будет изменяться в зависимости от содержимого, не больше и не меньше
  • Поэтому, если GridSplitter помещается между двумя * размерами строк / столбцов, то он неявно уважает ваш MinHeight, поскольку в действительности он не будет касаться его

У вас есть несколько решений

  1. Добавьте еще одну строку в 3-й позиции, которая имеет размер *, и поместите вашу границу в строку 3 с RowSpan, равным 2 (таким образом, 3-й ряд действительно изменен, а ваш 4-й ряд не затронут. Хотя это также будет иметь побочные эффекты.
  2. Обработка смеси событий DragEnter и PreviewMouseMove в GridSplitter, отслеживание фокуса и отмена (e.Handled = true) события при достижении определенного размера.

Это то, что я могу вспомнить, приятель, надеюсь, я чем-то помог.

1 голос
/ 03 мая 2016

Я создал собственный класс разделителя сетки, который не позволит разделителю сетки выходить за границы окна (ни снизу, ни сбоку).

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». Все работает как базовый разветвитель сетки.

При этом используются события мыши, чтобы определить, где в окне пользователь перетаскивает разделитель, и обрабатываются события, если они находятся слишком близко к краю.

0 голосов
/ 25 октября 2017

Я нашел другое решение этой проблемы, хотя в гораздо более простом случае, когда у меня было только два столбца внутри окна, размер которого я хотел изменить.

Решение, которое я придумал (более подробно описано здесь: 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);
...