Подтвердить что ты не робот

Стоп Gridsplitter растягивает содержимое за окном

Учитывая приведенный ниже 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>
4b9b3361

Ответ 1

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

Несколько точек

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

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

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

Это то, что я могу думать о помощнике, надеюсь, что я немного помог.

Ответ 2

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

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

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

Ответ 3

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

Решение, с которым я столкнулся (более подробно описано здесь: fooobar.com/info/244868/...), заключалось в том, чтобы добавлять обратные вызовы событий, когда сетка была изменена, когда 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>

Код С#:

C0.MaxWidth = Math.Min(ResizeGrid.ActualWidth, ActualWidth) - (C2.MinWidth + 5);