Wie bringen Sie die Kinder von StackPanel dazu, den maximalen Platz nach unten zu füllen?

356

Ich möchte einfach links fließenden Text und rechts ein Hilfefeld.

Das Hilfefeld sollte sich bis ganz nach unten erstrecken.

Wenn Sie das Äußere StackPanelunten herausnehmen, funktioniert es großartig.

Aber aus Gründen des Layouts (ich füge UserControls dynamisch ein) muss ich die Umhüllung haben StackPanel.

Wie kann ich das erreichen GroupBox, um bis zum Boden des zu reichen StackPanel, wie Sie sehen können, habe ich versucht:

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

Antworten:

Danke Mark, benutze es DockPanelanstatt StackPaneles zu klären. Im Allgemeinen verwende ich DockPaneljetzt immer mehr WPF-Layouts. Hier ist die feste 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" 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>
Edward Tanguay
quelle
Die Formatierung wurde korrigiert - es gefällt nicht, direkt von einer Liste zum Code zu wechseln
Greg
1
Können Sie eine GroupBox so alleine dehnen? Wenn ja, fügen Sie Ihre übergeordneten Elemente einzeln hinzu, bis Sie herausfinden, welches das Layout beschädigt.
Drew Noakes
RoBorg: Schön zu wissen, das hat mich verwirrt, danke
Edward Tanguay
1
Vielen Dank. Mit Ihrer Antwort konnte ich 2 verschachtelte DockPanels verwenden, um mein sehr ähnliches Problem zu lösen!
Yablargo

Antworten:

344

Es hört sich so an, als ob Sie eine möchten, StackPanelbei der das letzte Element den gesamten verbleibenden Platz belegt. Aber warum nicht ein DockPanel? Dekorieren Sie die anderen Elemente im DockPanelmit DockPanel.Dock="Top", und dann kann Ihre Hilfesteuerung den verbleibenden Platz ausfüllen.

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>

Wenn Sie sich auf einer Plattform befinden, die nicht DockPanelverfügbar ist (z. B. WindowsStore), können Sie denselben Effekt mit einem Raster erstellen. Hier ist das obige Beispiel, das stattdessen mit Gittern erstellt wurde:

<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>
Mark Heath
quelle
18
Brillant! Ich habe die letzte Stunde damit verbracht, herauszufinden, wie StackPanel dazu gebracht werden kann. Von nun an werde ich hier zuerst nach meinen WPF (und anderen) Informationen suchen.
Paxdiablo
7
Ich kann nicht glauben, wie viel Zeit ich damit verbracht habe, StackPanels dazu zu bringen, das zu tun, was ich wollte. Danke für das Teilen! DockPanels sind das, was ich die ganze Zeit wollte.
Danglund
Es gibt anscheinend kein Dockpanel für Tablets. telerik.com/forums/following-blog-post-and-comparison
JP Hellemons
1
Kein Dock Panel für Windows Store-Apps.
Teoman Shipahi
Jetzt dreht sich alles um universelle Apps und universelle Apps unterstützen DockPanel noch nicht?
Yonexbat
105

Der Grund dafür ist, dass das Stapelfenster jedes untergeordnete Element mit positiver Unendlichkeit als Einschränkung für die Achse misst, entlang der es Elemente stapelt. Die untergeordneten Steuerelemente müssen zurückgeben, wie groß sie sein möchten (positive Unendlichkeit ist keine gültige Rückgabe von MeasureOverride in beiden Achsen), damit sie die kleinste Größe zurückgeben, in die alles passt. Sie können nicht wissen, wie viel Platz sie wirklich füllen müssen.

Wenn Ihre Ansicht keine Bildlauffunktion benötigt und die obige Antwort nicht Ihren Anforderungen entspricht, würde ich vorschlagen, ein eigenes Panel zu implementieren. Sie können wahrscheinlich direkt von StackPanel ableiten. Anschließend müssen Sie lediglich die ArrangeOverride- Methode so ändern , dass der verbleibende Speicherplatz auf die untergeordneten Elemente aufgeteilt wird (wobei jeder den gleichen zusätzlichen Speicherplatz erhält ). Elemente sollten gut gerendert werden, wenn ihnen mehr Platz eingeräumt wird als gewünscht. Wenn Sie ihnen jedoch weniger Platz geben, werden Sie Störungen sehen.

Wenn Sie in der Lage sein möchten, das Ganze zu scrollen, werden die Dinge leider etwas schwieriger, da der ScrollViewer Ihnen unendlich viel Platz zum Arbeiten bietet, wodurch Sie in die gleiche Position gebracht werden wie die untergeordneten Elemente ursprünglich. In dieser Situation möchten Sie möglicherweise eine neue Eigenschaft in Ihrem neuen Bedienfeld erstellen, mit der Sie die Größe des Ansichtsfensters angeben können. Sie sollten diese an die Größe des ScrollViewer binden können. Idealerweise würden Sie IScrollInfo implementieren , aber das wird kompliziert, wenn Sie alles richtig implementieren.

Caleb Vear
quelle
+1, ich würde Ihnen mehr geben, aber nur 1 ist zulässig. In Ihrem ersten Absatz wurde darauf hingewiesen, was bei zahlreichen Microsoft-Seiten fehlgeschlagen ist, nämlich warum Unendlichkeit als Höhe / Breite auftreten kann und dass Sie sich nicht darauf verlassen können, availableSize von MeasureOverride zurückzugeben .
Aidan
Ein StackPanel in einem Grid löst sein häufig auftretendes Bedürfnis mit Leichtigkeit. Das untere Bit kann bei Bedarf in einen ScrollViewer eingefügt werden. Ich mache WPF seit 2006 und musste nur einmal ein benutzerdefiniertes Panel erstellen. Ich denke nicht, dass es eine gute Idee ist, zusätzliche Komplexität zu fördern.
Chris Bordeman
@ ChrisBordeman Ich bin nicht sicher, ob ich verstehe, wie das Stack-Panel im Raster das Problem löst. Die Idee ist, ein oder mehrere untergeordnete Elemente im Stapelfenster zu strecken, um den verfügbaren Platz zu füllen. Wenn Sie das Stack-Panel in ein Raster einfügen, funktioniert das nicht?
Caleb Vear
61

Eine alternative Methode besteht darin, ein Raster mit einer Spalte und n Zeilen zu verwenden. Stellen Sie alle Zeilenhöhen auf Autound die unterste Zeilenhöhe auf ein 1*.

Ich bevorzuge diese Methode, da ich festgestellt habe, dass Grids eine bessere Layoutleistung aufweisen als DockPanels, StackPanels und WrapPanels. Aber wenn Sie sie nicht in einer ItemTemplate verwenden (wo das Layout für eine große Anzahl von Elementen ausgeführt wird), werden Sie es wahrscheinlich nie bemerken.

rcabr
quelle
1
für mich die beste lösung. Damit ist es möglich, mehr als eine wachsende Reihe zu definieren
Uhr
18

Sie können SpicyTaco.AutoGrid verwenden - eine modifizierte Version von 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>

Die erste Schaltfläche wird ausgefüllt.

Sie können es über NuGet installieren:

Install-Package SpicyTaco.AutoGrid

Ich empfehle einen Blick auf SpicyTaco.AutoGrid . Es ist sehr nützlich für Formulare in WPF statt DockPanel, StackPanelund Gridund löst Problem mit Strecken sehr einfach und elegant. Schauen Sie sich einfach die Readme-Datei auf GitHub an.

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

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

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