Come fare in modo che i figli di StackPanel riempiano lo spazio massimo verso il basso?


356

Voglio semplicemente scorrere il testo a sinistra e una casella di aiuto a destra.

La casella di aiuto dovrebbe estendersi fino in fondo.

Se estrai l'esterno StackPanelsottostante, funziona alla grande.

Ma per motivi di layout (sto inserendo UserControls in modo dinamico) ho bisogno del wrapping StackPanel.

Come faccio GroupBoxad estendere fino alla fine di StackPanel, come puoi vedere, ho provato:

  • VerticalAlignment="Stretch"
  • VerticalContentAlignment="Stretch"
  • Height="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>

Risposta:

Grazie Marco, usando DockPanelinvece di StackPanelchiarirlo. In generale, mi ritrovo a usare DockPanelsempre di più ora per il layout WPF, ecco l'XAML fisso:

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

Risolto il problema con la formattazione - non gli piace passare direttamente da un elenco a codice
Greg,

1
Puoi allungare un GroupBox in questo modo da solo? In tal caso, inizia ad aggiungere gli elementi padre uno a uno fino a scoprire quale sta rompendo il layout.
Drew Noakes,

RoBorg: bello da sapere, mi ha lasciato perplesso, grazie
Edward Tanguay,

1
Grazie. Usando la tua risposta sono stato in grado di utilizzare 2 DockPanel nidificati per risolvere il mio problema molto simile!
Yablargo,

Risposte:


344

Sembra che tu voglia un StackPanelelemento in cui l'elemento finale occupa tutto lo spazio rimanente. Ma perché non usare un DockPanel? Decorare gli altri elementi DockPanelcon DockPanel.Dock="Top", quindi il controllo della guida può riempire lo spazio rimanente.

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>

Se sei su una piattaforma senza DockPaneldisponibile (ad esempio WindowsStore), puoi creare lo stesso effetto con una griglia. Ecco invece l'esempio sopra realizzato usando le griglie:

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

18
Brillante! Ho trascorso l'ultima ora a cercare di capire come far fare StackPanel a farlo. D'ora in poi, cercherò prima qui le mie informazioni WPF (e altre).
paxdiablo,

7
Non riesco a credere quanto tempo ho trascorso cercando di far fare a StackPanels quello che volevo. Grazie per la condivisione! DockPanels è quello che volevo da sempre.
danglund,

Sembra che non ci sia dockpanel per tablet. telerik.com/forums/following-blog-post-and-comparison
JP Hellemons,

1
Nessun pannello dock per le app di Windows Store.
Teoman Shipahi,

Ora si tratta solo di app universali e le app universali non supportano ancora DockPanel?
yonexbat,

105

Il motivo per cui ciò sta accadendo è perché il pannello di stack misura ogni elemento figlio con infinito positivo come vincolo per l'asse su cui sta impilando gli elementi. I controlli figlio devono restituire quanto vogliono essere grandi (l'infinito positivo non è un ritorno valido da MeasureOverride su entrambi gli assi) in modo da restituire la dimensione più piccola dove tutto si adatterà. Non hanno modo di sapere quanto spazio devono davvero riempire.

Se la tua vista non ha bisogno di avere una funzione di scorrimento e la risposta sopra non soddisfa le tue esigenze, ti suggerirei di implementare il tuo pannello. Probabilmente puoi derivare direttamente da StackPanel e quindi tutto ciò che dovrai fare è cambiare il metodo ArrangeOverride in modo che divida lo spazio rimanente tra i suoi elementi figlio (dando a ciascuno la stessa quantità di spazio extra). Gli elementi dovrebbero rendere bene se ricevono più spazio di quanto desiderassero, ma se dai loro meno inizierai a vedere i difetti.

Se vuoi essere in grado di scorrere l'intera cosa, temo che le cose saranno un po 'più difficili, perché ScrollViewer ti dà una quantità infinita di spazio con cui lavorare che ti porterà nella stessa posizione degli elementi figlio originariamente. In questa situazione potresti voler creare una nuova proprietà sul tuo nuovo pannello che ti consenta di specificare la dimensione del viewport, dovresti essere in grado di associarlo alla dimensione di ScrollViewer. Idealmente dovresti implementare IScrollInfo , ma questo inizia a complicarsi se hai intenzione di implementarlo correttamente.


+1, ti darei di più ma solo 1 è consentito, il tuo primo paragrafo ha sottolineato ciò che numerose pagine Microsoft non sono riuscite, vale a dire perché l'infinito può verificarsi come altezza / larghezza e il fatto che non puoi fare affidamento sul ritorno disponibile .
Aidan,

Uno StackPanel all'interno di una griglia risolve il suo bisogno piuttosto comune con grande facilità. Il bit in basso potrebbe essere inserito in uno ScrollViewer, se necessario. Faccio WPF dal 2006 e ho sempre avuto bisogno solo di un pannello personalizzato. Non credo sia una buona idea incoraggiare una maggiore complessità.
Chris Bordeman,

@ChrisBordeman Non sono sicuro di capire come il pannello dello stack all'interno della griglia risolva il problema. L'idea è di avere uno o più elementi figlio nel riquadro dello stack per allungare lo spazio disponibile. Mettere il pannello dello stack all'interno di una griglia non lo fa fare così?
Caleb Vear, il

61

Un metodo alternativo consiste nell'utilizzare una griglia con una colonna e n righe. Impostare tutte le altezze delle righe su Autoe l'altezza della riga più in basso su 1*.

Preferisco questo metodo perché ho scoperto che le griglie hanno prestazioni di layout migliori rispetto a DockPanels, StackPanels e WrapPanels. Ma se non li usi in un ItemTemplate (dove il layout viene eseguito per un gran numero di elementi), probabilmente non lo noterai mai.


1
per me la migliore soluzione. con questo è possibile definire più di una riga crescente
niyou

18

Puoi usare SpicyTaco.AutoGrid - una versione modificata di 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>

Il primo pulsante verrà riempito.

Puoi installarlo tramite NuGet:

Install-Package SpicyTaco.AutoGrid

Consiglio di dare un'occhiata a SpicyTaco.AutoGrid . E 'molto utile per le forme in WPF invece DockPanel, StackPaneled Gride risolvere un problema con allungamento molto semplice e con grazia. Guarda il readme su GitHub.

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

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

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.