web-dev-qa-db-fra.com

Comment faire en sorte que les enfants StackPanel remplissent le maximum d’espace vers le bas?

Je veux simplement un texte fluide à gauche et une boîte d’aide à droite.

La boîte d’aide devrait s’étendre jusqu’en bas.

Si vous retirez le StackPanel externe ci-dessous, cela fonctionne très bien.

Mais pour des raisons de mise en page (j'insère UserControls de manière dynamique), je dois disposer du wrapper StackPanel.

Comment puis-je faire en sorte que la GroupBox s'étende jusqu'au bas du StackPanel, comme vous pouvez le constater, j'ai déjà essayé:

  • VerticalAlignment = "Stretch"
  • VerticalContentAlignment = "Stretch"
  • Hauteur = "Auto"

XAML:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600">
    <StackPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                Background="Beige" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" />
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </StackPanel>
</Window>

Répondre:

Merci Mark, l’utilisation de DockPanel au lieu de StackPanel a permis de résoudre le problème. En général, je me retrouve de plus en plus à utiliser DockPanel pour la mise en page WPF, voici le XAML corrigé:

<Window x:Class="TestDynamic033.Test3"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Title="Test3" Height="300" Width="600" MinWidth="500" MinHeight="200">
    <DockPanel 
        VerticalAlignment="Stretch" 
        Height="Auto">

        <DockPanel 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch" 
            Height="Auto" 
            MinWidth="400"
            Margin="10">

            <GroupBox 
                DockPanel.Dock="Right" 
                Header="Help" 
                Width="100" 
                VerticalAlignment="Stretch" 
                VerticalContentAlignment="Stretch" 
                Height="Auto">
                <Border CornerRadius="3" Background="Beige">
                    <TextBlock Text="This is the help that is available on the news screen." TextWrapping="Wrap" 

                Padding="5"/>
                </Border>
            </GroupBox>

            <StackPanel DockPanel.Dock="Left" Margin="10" Width="Auto" HorizontalAlignment="Stretch">
                <TextBlock Text="Here is the news that should wrap around." TextWrapping="Wrap"/>
            </StackPanel>

        </DockPanel>
    </DockPanel>
</Window>
332
Edward Tanguay

On dirait que vous voulez un StackPanel où l’élément final utilise tout l’espace restant. Mais pourquoi ne pas utiliser un DockPanel? Décorez les autres éléments de la DockPanel avec DockPanel.Dock="Top", puis le contrôle de votre aide pourra remplir l'espace restant.

XAML:

<DockPanel Width="200" Height="200" Background="PowderBlue">
    <TextBlock DockPanel.Dock="Top">Something</TextBlock>
    <TextBlock DockPanel.Dock="Top">Something else</TextBlock>
    <DockPanel
        HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" 
        Height="Auto" 
        Margin="10">

      <GroupBox 
        DockPanel.Dock="Right" 
        Header="Help" 
        Width="100" 
        Background="Beige" 
        VerticalAlignment="Stretch" 
        VerticalContentAlignment="Stretch" 
        Height="Auto">
        <TextBlock Text="This is the help that is available on the news screen." 
                   TextWrapping="Wrap" />
     </GroupBox>

      <StackPanel DockPanel.Dock="Left" Margin="10" 
           Width="Auto" HorizontalAlignment="Stretch">
          <TextBlock Text="Here is the news that should wrap around." 
                     TextWrapping="Wrap"/>
      </StackPanel>
    </DockPanel>
</DockPanel>

Si vous êtes sur une plate-forme pour laquelle DockPanel n'est pas disponible (WindowsStore, par exemple), vous pouvez créer le même effet avec une grille. Voici l'exemple ci-dessus réalisé à l'aide de grilles à la place:

<Grid Width="200" Height="200" Background="PowderBlue">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0">
        <TextBlock>Something</TextBlock>
        <TextBlock>Something else</TextBlock>
    </StackPanel>
    <Grid Height="Auto" Grid.Row="1" Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <GroupBox
            Width="100"
            Height="Auto"
            Grid.Column="1"
            Background="Beige"
            Header="Help">
            <TextBlock Text="This is the help that is available on the news screen." 
              TextWrapping="Wrap"/>
        </GroupBox>
        <StackPanel Width="Auto" Margin="10" DockPanel.Dock="Left">
            <TextBlock Text="Here is the news that should wrap around." 
              TextWrapping="Wrap"/>
        </StackPanel>
    </Grid>
</Grid>
317
Mark Heath

La raison en est que le panneau de pile mesure chaque élément enfant avec l'infini positif comme contrainte pour l'axe sur lequel il empile les éléments. Les contrôles enfants doivent renvoyer la taille souhaitée (l'infini positif n'est pas un retour valide de MeasureOverride dans l'un ou l'autre des axes) afin qu'ils renvoient la plus petite taille où tout ira bien. Ils n'ont aucun moyen de savoir combien d'espace ils doivent vraiment remplir.

Si votre vue n’a pas besoin de fonction de défilement et que la réponse ci-dessus ne correspond pas à vos besoins, je vous suggère d’implémenter votre propre panneau. Vous pouvez probablement dériver directement de StackPanel et tout ce que vous aurez à faire est de changer la méthode ArrangeOverride de sorte qu'elle divise l'espace restant entre ses éléments enfants (en leur donnant la même quantité d'espace supplémentaire) . Les éléments devraient rendre bien si on leur donne plus d'espace qu'ils ne le voulaient, mais si vous leur en donnez moins, vous commencerez à voir des problèmes.

Si vous voulez pouvoir faire défiler le texte entier, je crains que cela ne soit un peu plus difficile, car ScrollViewer vous laisse une infinité d'espace pour travailler, ce qui vous placera dans la même position que les éléments enfants. à l'origine. Dans ce cas, vous souhaiterez peut-être créer une nouvelle propriété sur votre nouveau panneau qui vous permettra de spécifier la taille de la fenêtre d'affichage. Vous devriez pouvoir la lier à la taille de ScrollViewer. Idéalement, vous devriez implémenter IScrollInfo , mais cela commence à se compliquer si vous voulez tout mettre en œuvre correctement.

102
Caleb Vear

Une autre méthode consiste à utiliser une grille avec une colonne et n lignes. Définissez toutes les hauteurs de ligne sur Auto et la hauteur la plus basse sur 1*.

Je préfère cette méthode car j'ai constaté que les grilles offrent de meilleures performances de disposition que DockPanels, StackPanels et WrapPanels. Mais à moins que vous ne les utilisiez dans un ItemTemplate (où la mise en page est effectuée pour un grand nombre d'éléments), vous ne le remarquerez probablement jamais.

56
rcabr

Vous pouvez utiliser version modifiée de StackPanel:

<st:StackPanel Orientation="Horizontal" MarginBetweenChildren="10" Margin="10">
   <Button Content="Info" HorizontalAlignment="Left" st:StackPanel.Fill="Fill"/>
   <Button Content="Cancel"/>
   <Button Content="Save"/>
</st:StackPanel>

Le premier bouton sera rempli.

Vous pouvez l'installer via Nuget:

Install-Package SpicyTaco.AutoGrid

Je recommande également de jeter un oeil à wpf-autogrid . Il est très utile pour les formulaires dans WPF au lieu de DockPanel, StackPanel et Grid et résout le problème avec l’étirement très facilement et avec élégance. Il suffit de regarder le readme sur github.

<st:AutoGrid Columns="160,*" ChildMargin="3">
    <Label Content="Name:"/>
    <TextBox/>

    <Label Content="E-Mail:"/>
    <TextBox/>

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>
14
Dvor_nik