property form bindings wpf gridsplitter

form - wpf bindings



Detener Gridsplitter estirar el contenido más allá de la ventana (3)

Dado el siguiente XAML, ¿cómo puedo hacer que Gridsplitter respete el MinHeight dado a la 3ª fila y que el contenido permanezca dentro de mi ventana?

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


Creé una clase de divisor de cuadrícula personalizada que no permitirá que el divisor de cuadrícula salga del borde de una ventana (ya sea la parte inferior o el lateral).

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

Clase final

Para usarlo en 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"/>

Las propiedades personalizadas para establecer son "SplitterDirection" y "MinimumDistanceFromEdge". Todo funciona como el separador de rejilla base.

Esto utiliza eventos del mouse para determinar en qué parte de la ventana el usuario está arrastrando el divisor y maneja los eventos si se acercan demasiado al borde.


Encontré otra solución a este problema, aunque en un caso mucho más simple en el que solo tenía dos columnas dentro de una ventana que quería cambiar de tamaño.

La solución que se me ocurrió (que se describe con más detalle aquí: https://.com/a/46924893/6481970 ) fue agregar devoluciones de llamada de eventos para cuando se cambió el tamaño de la cuadrícula, cuando se movió el GridSplitter y cuando se abrió la ventana redimensionado (para controlar el caso en el que se redimensiona la ventana para que ya no se ajuste al contenido porque la cuadrícula no se redimensiona automáticamente para ajustarse a la ventana más pequeña).

Aquí hay un código simplificado:

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ódigo C # Detrás:

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


La forma en que su código es, esto no se puede hacer amigo. Esto se debe a cómo funciona el GridSplitter.

Algunos puntos

  • Un GridSplitter siempre funcionará en filas / columnas directamente adyacentes
  • En realidad, su MinHeight ESTÁ siendo respetada, pero también lo es la solicitud de GridSplitter para crecer y ser respetado, lo que hace que Grid crezca más que su Ventana
  • Cuando se ajusta en tamaño a Automático, una fila / columna siempre cambiará de tamaño según su contenido, no más grande ni más pequeña
  • Por lo tanto, si un GridSplitter está emparedado entre dos * filas / columnas de tamaño, entonces respetaría implícitamente su MinHeight, ya que en realidad, no lo tocaría

Tienes algunas soluciones

  1. Agregue otra fila en la tercera posición, que es de tamaño *, y haga que su borde en la fila 3 tenga un RowSpan de 2 (entonces la tercera fila es la que está siendo redimensionada, y su cuarta fila no se toca. Aunque esto también tendrá efectos secundarios.
  2. Maneja una mezcla de eventos DragEnter y PreviewMouseMove en el GridSplitter, manteniendo un seguimiento del enfoque y cancelando (e.Handled = true) el evento cuando se alcanza un tamaño determinado.

Esto es lo que puedo pensar de mi compañero, espero haber sido de alguna ayuda.