วิธีทำให้ลูกของ StackPanel เติมเต็มพื้นที่สูงสุดลงได้อย่างไร


356

ฉันต้องการข้อความต่อเนื่องทางซ้ายและกล่องช่วยเหลือทางด้านขวา

กล่องความช่วยเหลือควรขยายไปจนถึงด้านล่างสุด

ถ้าคุณถอดด้านนอกออกStackPanelมันใช้งานได้ดีมาก

แต่สำหรับเหตุผลของการจัดวาง (ฉันกำลังแทรก UserControls แบบไดนามิก) ฉันต้องมีการตัดStackPanelคำ

ฉันจะได้รับการGroupBoxขยายลงไปที่ด้านล่างของStackPanelตามที่คุณเห็นฉันได้ลอง:

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

ตอบ:

ขอขอบคุณมาร์คใช้DockPanelแทนStackPanelล้างมันขึ้นมา โดยทั่วไปแล้วฉันพบว่าตัวเองกำลังใช้DockPanelการจัดวาง WPF มากขึ้นเรื่อย ๆ นี่คือ 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>

การจัดรูปแบบคงที่ - มันไม่ชอบจะตรงจากรายการรหัส
เกร็ก

1
คุณสามารถสร้าง GroupBox ได้ด้วยวิธีนี้หรือไม่ หากเป็นเช่นนั้นให้เริ่มเพิ่มองค์ประกอบหลักของคุณทีละรายการจนกว่าคุณจะพบว่าองค์ประกอบใดกำลังทำลายเค้าโครง
Drew Noakes

RoBorg: ดีใจที่ได้รู้ว่าฉันงุนงงขอบคุณ
Edward Tanguay

1
ขอบคุณ ใช้คำตอบของคุณฉันสามารถใช้ DockPanels 2 อันซ้อนกันเพื่อแก้ปัญหาที่คล้ายกันของฉัน!
Yablargo

คำตอบ:


344

ดูเหมือนว่าคุณต้องการStackPanelองค์ประกอบสุดท้ายที่ใช้พื้นที่ที่เหลือทั้งหมด แต่ทำไมไม่ใช้DockPanel? ตกแต่งองค์ประกอบอื่น ๆDockPanelด้วยDockPanel.Dock="Top"และจากนั้นการควบคุมความช่วยเหลือของคุณสามารถเติมพื้นที่ที่เหลือ

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>

หากคุณอยู่บนแพลตฟอร์มที่ไม่มีDockPanelให้ใช้งาน (เช่น WindowsStore) คุณสามารถสร้างเอฟเฟกต์แบบเดียวกันกับกริด นี่คือตัวอย่างข้างต้นที่ทำได้โดยใช้กริดแทน:

<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
ยอดเยี่ยม! ฉันใช้เวลาในชั่วโมงสุดท้ายเพื่อหาวิธีใช้ StackPanel ในการทำสิ่งนี้ จากนี้ไปฉันจะดูที่นี่ก่อนเพื่อรับข้อมูล WPF (และอื่น ๆ ) ของฉัน
paxdiablo

7
ฉันไม่อยากจะเชื่อเลยว่าฉันต้องใช้เวลามากแค่ไหนในการทำให้ StackPanels ทำสิ่งที่ฉันต้องการ ขอบคุณสำหรับการแบ่งปัน! DockPanels เป็นสิ่งที่ฉันต้องการมาตลอด
danglund

ดูเหมือนไม่มีแท่นวางสำหรับแท็บเล็ตที่ดูเหมือนว่า telerik.com/forums/following-blog-post-and-comparison
JP

1
ไม่มีแผงพาเนลสำหรับแอพ Windows Store
Teoman shipahi

ตอนนี้มันเป็นเรื่องของแอพสากลและแอพสากลที่ยังไม่รองรับ DockPanel?
yonexbat

105

เหตุผลที่สิ่งนี้เกิดขึ้นเนื่องจากสแต็คพาเนลวัดองค์ประกอบลูกทุกตัวที่มีค่าอนันต์บวกเป็นข้อ จำกัด สำหรับแกนที่สแตกองค์ประกอบ ตัวควบคุมลูกจะต้องคืนค่าขนาดที่พวกเขาต้องการ (อินฟินิตี้บวกไม่ใช่ผลตอบแทนที่ถูกต้องจากMeasureOverrideในแต่ละแกน) ดังนั้นพวกเขาจึงกลับขนาดที่เล็กที่สุดซึ่งทุกอย่างจะพอดี พวกเขาไม่มีทางรู้เลยว่าพวกเขาต้องเติมเต็มพื้นที่เท่าไหร่

หากมุมมองของคุณไม่จำเป็นต้องมีคุณสมบัติการเลื่อนและคำตอบข้างต้นไม่เหมาะกับความต้องการของคุณฉันขอแนะนำให้ใช้แผงควบคุมของคุณเอง คุณอาจได้รับโดยตรงจาก StackPanel และสิ่งที่คุณต้องทำคือเปลี่ยนเมธอดArrangeOverrideเพื่อให้แบ่งพื้นที่ที่เหลืออยู่ระหว่างองค์ประกอบลูก (ให้แต่ละพื้นที่พิเศษเท่ากัน) องค์ประกอบควรแสดงผลได้ดีหากมีพื้นที่มากกว่าที่ต้องการ แต่ถ้าคุณให้น้อยลงคุณจะเริ่มเห็นข้อบกพร่อง

หากคุณต้องการเลื่อนดูทั้งหมดฉันก็กลัวว่าสิ่งต่าง ๆ จะยากขึ้นอีกเล็กน้อยเพราะ ScrollViewer ให้พื้นที่ในการทำงานที่ไม่ จำกัด ซึ่งจะทำให้คุณอยู่ในตำแหน่งเดียวกับองค์ประกอบลูก แต่เดิม ในสถานการณ์นี้คุณอาจต้องการสร้างพร็อพเพอร์ตี้ใหม่บนพาเนลใหม่ของคุณซึ่งช่วยให้คุณระบุขนาดวิวพอร์ตคุณควรจะเชื่อมโยงกับขนาดของ ScrollViewer เป็นการดีที่คุณจะใช้IScrollInfoแต่นั่นเริ่มมีความซับซ้อนหากคุณจะใช้ทั้งหมดอย่างถูกต้อง


+1 ฉันจะให้คุณมากกว่า แต่อนุญาตเพียง 1 ย่อหน้าแรกของคุณชี้ให้เห็นว่าหน้า Microsoft จำนวนมากล้มเหลวนั่นคือสาเหตุที่อินฟินิตี้สามารถเกิดขึ้นได้ในระดับความสูง / ความกว้างและความจริงที่ว่าคุณไม่สามารถไว้ใจได้ .
Aidan

StackPanel ภายใน Grid แก้ไขความต้องการทั่วไปของเขาได้อย่างง่ายดาย บิตด้านล่างสามารถใส่ใน ScrollViewer ได้ถ้าจำเป็น ฉันทำ WPF มาตั้งแต่ปี 2549 และมีความจำเป็นเพียงครั้งเดียวในการทำพาเนลแบบกำหนดเอง ฉันไม่คิดว่ามันเป็นความคิดที่ดีที่จะส่งเสริมความซับซ้อนเป็นพิเศษ
Chris Bordeman

@ ChrisBordeman ฉันไม่แน่ใจว่าฉันเข้าใจว่าแผงสแต็คภายในตารางแก้ปัญหาได้อย่างไร แนวคิดคือมีองค์ประกอบลูกหนึ่งรายการขึ้นไปในแผงสแต็กยืดเพื่อเติมเต็มพื้นที่ว่าง การวางพาเนลสแต็กไว้ในตารางไม่ได้ทำอย่างนั้นหรือ
Caleb Vear

61

วิธีทางเลือกคือการใช้ตารางที่มีคอลัมน์หนึ่งและnแถว การตั้งค่าทั้งหมดที่สูงแถวและล่างสุดความสูงของแถวไปAuto1*

ฉันชอบวิธีนี้เพราะฉันพบว่ากริดมีประสิทธิภาพการจัดวางที่ดีกว่า DockPanels, StackPanels และ WrapPanels แต่ถ้าคุณไม่ได้ใช้มันใน ItemTemplate (ซึ่งมีการจัดวางเลย์เอาต์สำหรับรายการจำนวนมาก) คุณอาจไม่เคยสังเกตเห็นเลย


1
สำหรับฉันทางออกที่ดีที่สุด ด้วยสิ่งนี้มันเป็นไปได้ที่จะนิยามแถวที่เพิ่มขึ้นหนึ่งแถว
niyou

18

คุณสามารถใช้SpicyTaco.AutoGrid - รุ่นที่แก้ไขของ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>

ปุ่มแรกจะถูกกรอกข้อมูล

คุณสามารถติดตั้งผ่านทาง NuGet:

Install-Package SpicyTaco.AutoGrid

เราขอแนะนำให้ดูที่SpicyTaco.AutoGrid มันมีประโยชน์มากสำหรับรูปแบบใน WPF แทนDockPanel, StackPanelและGridและแก้ปัญหาเกี่ยวกับการยืดง่ายและสง่างาม เพียงดูที่ readme บน GitHub

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

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

    <Label Content="Comment:"/>
    <TextBox/>
</st:AutoGrid>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.