2010-10-19 4 views
13

Je souhaite une disposition de grille avec deux lignes et séparateur entre elles. Les lignes doivent avoir une hauteur minimale de 80 pixels.GridSplitter avec des contraintes min

Ce code fonctionne très 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> 

Mais je veux la rangée supérieure d'avoir une hauteur automatique jusqu'à ce que l'utilisateur modifie manuellement en utilisant le séparateur. Donc, j'ai changé le code à ceci:

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

Et il y a un problème. Splitter satisfait toujours les contraintes de ligne, mais il commence à augmenter infiniment la hauteur de la rangée supérieure si je fais glisser le splitter trop bas. Il en résulte que la ligne du bas est complètement en dessous de la bordure inférieure de la fenêtre.

J'ai fait un peu de réflecteur sur le code GridSplitter et je vois qu'il utilise une logique différente si les lignes ont une hauteur Auto ou Star.

Des suggestions comment puis-je "réparer"?

Répondre

5

J'ai développé une solution de contournement pour ce problème. Le point est de définir MaxHeight pour la ligne du haut pendant que nous déplaçons le séparateur. Voici le code:

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

Ensuite, remplacez simplement GridSplitter avec FixedGridSplitter.

Remarque: ce code n'est pas général - il ne prend pas en charge les colonnes et suppose que la ligne inférieure a la valeur MinHeight.

5

J'ai moi-même rencontré ce problème plusieurs fois. Il semble que le GridSplitter ne joue pas bien avec Auto. Cela dit, j'ai trouvé une solution de contournement potentielle.

Vous pouvez spécifier la valeur d'un objet GridLength en utilisant "coefficients d'étoile". Cela agit comme un multiplicateur pour la longueur en question. Dans votre exemple, si vous prenez la ligne que vous voulez conserver comme étoile et que vous placez le coefficient étoile à un nombre vraiment important, la ligne occupera tout l'espace disponible (forçant l'autre rangée à devenir sa minuscule). la taille). Bien que ce ne soit pas le même comportement que "auto" (la hauteur de la première rangée n'est pas déterminée par la hauteur de son contenu), cela pourrait vous rapprocher.

<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

Merci, mais je veux enregistrer une logique automatique – Seldon

+0

Cela a fonctionné avec brio pour moi, maintenant le dimensionnement fonctionne parfaitement. – Contango