2010-10-19 23 views
13

Desidero un layout Grid con due righe e uno splitter tra di loro. Le file dovrebbero avere un'altezza minima di 80 pixel.GridSplitter con vincoli minimi

Questo codice funziona alla grande:

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

Ma voglio riga superiore di avere un'altezza Auto fino all'utente di modificare manualmente utilizzando il divisore. Così ho cambiato il codice a questo:

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

E c'è un problema. Lo splitter soddisfa ancora i vincoli di riga, ma inizia ad aumentare l'altezza della riga superiore in modo infinito se trascino lo splitter troppo in basso. Ciò comporta che la riga inferiore sia completamente al di sotto del bordo inferiore della finestra.

Ho fatto qualche riflessione sul codice GridSplitter e vedo che usa una logica diversa se le righe hanno altezza Auto o Stella.

Qualche suggerimento come posso "aggiustarlo"?

risposta

5

Ho sviluppato una soluzione per questo problema. Il punto è impostare MaxHeight per la riga superiore mentre stiamo trascinando lo splitter. Qui il codice:

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

Quindi basta sostituire GridSplitter con FixedGridSplitter.

Nota: questo codice non è generale, non supporta colonne e presuppone che la riga inferiore abbia MinHeight specificato.

5

Ho incontrato questo problema un paio di volte. Sembra che GridSplitter non giochi bene con Auto. Detto questo, ho trovato una soluzione potenziale.

È possibile specificare il valore di un oggetto GridLength utilizzando "coefficienti stellari". Questo funge da moltiplicatore per la lunghezza in questione.

Nell'esempio, se si prende la riga che si desidera mantenere come stella e si imposta il coefficiente di stella su un numero molto grande, la riga occuperà tutto lo spazio disponibile (forzando l'altra riga a diventare la sua minima altezza). Anche se questo non è lo stesso comportamento di "auto" (l'altezza della prima riga non è determinata dalla sua altezza del contenuto), potrebbe avvicinarti.

<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

Grazie, ma voglio salvare una logica Auto – Seldon

+0

Questo ha funzionato perfettamente per me, ora il dimensionamento funziona perfettamente. – Contango