2010-10-19 20 views
13

Quiero un diseño de cuadrícula con dos filas y divisor entre ellas. Las filas deben tener una altura mínima de 80 píxeles.GridSplitter con restricciones mínimas

Este código funciona muy bien:

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

Pero quiero fila superior para tener una altura automática hasta que el usuario cambie manualmente utilizando el divisor. Así que cambié el código a este:

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

Y hay un problema. El divisor aún satisface las restricciones de fila, pero comienza a aumentar la altura de la fila superior infinitamente si arrastro el divisor demasiado bajo. Esto hace que la fila inferior esté completamente debajo del borde inferior de la ventana.

He hecho un Reflector en el código GridSplitter y veo que usa una lógica diferente si las filas tienen altura automática o de estrella.

¿Alguna sugerencia de cómo puedo "arreglarlo"?

Respuesta

5

He desarrollado una solución para este problema. Point es establecer MaxHeight para la fila superior mientras estamos arrastrando splitter. Aquí el código:

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

Luego simplemente reemplace GridSplitter con FixedGridSplitter.

Nota: este código no es general, no admite columnas y supone que la fila inferior tiene especificado MinHeight.

5

Me he encontrado con este problema algunas veces. Parece que el GridSplitter no funciona bien con Auto. Dicho esto, he encontrado una posible solución.

Puede especificar el valor de un objeto GridLength usando "coeficientes estelares". Esto actúa como un multiplicador para la longitud en cuestión.

En su ejemplo, si toma la fila que desea permanecer como estrella, y establece el coeficiente de estrella en un número realmente grande, la fila ocupará todo el espacio disponible (forzando a la otra fila a convertirse en su altura). Si bien este no es el mismo comportamiento que "automático" (la altura de la primera fila no está determinada por la altura de su contenido), podría acercarse más.

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

Gracias, pero quiero guardar una lógica automática – Seldon

+0

Esto funcionó de maravilla para mí, ahora el tamaño funciona perfectamente. – Contango

Cuestiones relacionadas