Bagaimana cara membuat anak-anak StackPanel mengisi ruang maksimum ke bawah?

356

Saya hanya ingin teks yang mengalir di sebelah kiri, dan kotak bantuan di sebelah kanan.

Kotak bantuan harus memanjang hingga ke bawah.

Jika Anda mengambil bagian luar di StackPanelbawahnya, itu bekerja dengan baik.

Tetapi karena alasan tata letak (saya memasukkan UserControls secara dinamis) saya harus memiliki pembungkusnya StackPanel.

Bagaimana cara mendapatkan GroupBoxuntuk memperluas ke bagian bawah StackPanel, seperti yang Anda lihat saya sudah mencoba:

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

Menjawab:

Terima kasih Mark, menggunakan DockPanelalih-alih StackPanelmembersihkannya. Secara umum, saya DockPanelsemakin sering menggunakan tata letak WPF sekarang, inilah XAML yang diperbaiki:

<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
sumber
Memperbaiki format - tidak suka langsung dari daftar ke kode
Greg
1
Bisakah Anda membuat peregangan GroupBox dengan cara itu sendiri? Jika demikian, mulailah menambahkan elemen induk Anda satu demi satu hingga Anda mengetahui elemen mana yang melanggar tata letak.
Drew Noakes
RoBorg: senang tahu, itu membuat saya bingung, terima kasih
Edward Tanguay
1
Terima kasih. Menggunakan jawaban Anda, saya bisa menggunakan 2 DockPanels bersarang untuk menyelesaikan masalah saya yang sangat mirip!
Yablargo

Jawaban:

344

Sepertinya Anda menginginkan tempat di StackPanelmana elemen terakhir menggunakan semua ruang yang tersisa. Tapi mengapa tidak menggunakan DockPanel? Hiasi elemen-elemen lain dalam DockPaneldengan DockPanel.Dock="Top", dan kemudian kontrol bantuan Anda dapat mengisi ruang yang tersisa.

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>

Jika Anda berada di platform tanpa DockPaneltersedia (mis. WindowsStore), Anda dapat membuat efek yang sama dengan kisi. Inilah contoh di atas yang diselesaikan menggunakan kisi:

<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
sumber
18
Cemerlang! Saya telah menghabiskan satu jam terakhir untuk mencari tahu bagaimana membuat StackPanel melakukan ini. Mulai sekarang, saya akan mencari di sini dulu untuk info WPF saya (dan lainnya).
paxdiablo
7
Saya tidak percaya berapa banyak waktu yang saya habiskan untuk mencoba membuat StackPanels melakukan apa yang saya inginkan. Terima kasih telah berbagi! DockPanels adalah apa yang saya inginkan selama ini.
danglund
Sepertinya tidak ada dockpanel untuk tablet. telerik.com/forums/following-blog-post-and-comparison
JP Hellemons
1
Tidak ada panel dock untuk aplikasi Windows Store.
Teoman shipahi
Sekarang semuanya tentang aplikasi universal dan aplikasi universal belum mendukung DockPanel?
yonexbat
105

Alasan hal ini terjadi adalah karena panel stack mengukur setiap elemen anak dengan infinity positif sebagai kendala untuk sumbu yang menumpuk elemen. Kontrol anak harus mengembalikan seberapa besar yang mereka inginkan (infinity positif bukan pengembalian yang valid dari MeasureOverride di kedua sumbu) sehingga mereka mengembalikan ukuran terkecil di mana semuanya akan cocok. Mereka tidak tahu berapa banyak ruang yang harus mereka isi.

Jika tampilan Anda tidak perlu memiliki fitur gulir dan jawaban di atas tidak sesuai dengan kebutuhan Anda, saya sarankan menerapkan panel Anda sendiri. Anda mungkin dapat mengambil langsung dari StackPanel dan semua yang perlu Anda lakukan adalah mengubah metode ArrangeOverride sehingga membagi ruang yang tersisa di antara elemen turunannya (memberi mereka masing-masing jumlah ruang ekstra yang sama). Unsur-unsur harus membuat baik jika mereka diberi lebih banyak ruang daripada yang mereka inginkan, tetapi jika Anda memberi mereka lebih sedikit Anda akan mulai melihat gangguan.

Jika Anda ingin dapat menggulir semuanya maka saya khawatir semuanya akan menjadi sedikit lebih sulit, karena ScrollViewer memberi Anda jumlah ruang yang tidak terbatas untuk bekerja dengan yang akan menempatkan Anda pada posisi yang sama dengan elemen anak. semula. Dalam situasi ini Anda mungkin ingin membuat properti baru di panel baru Anda yang memungkinkan Anda menentukan ukuran viewport, Anda harus dapat mengikat ini ke ukuran ScrollViewer. Idealnya Anda akan menerapkan IScrollInfo , tetapi itu mulai menjadi rumit jika Anda akan menerapkan semua itu dengan benar.

Caleb Vear
sumber
+1, saya akan memberi Anda lebih banyak tetapi hanya 1 yang diizinkan, paragraf pertama Anda telah menunjukkan apa yang banyak halaman Microsoft gagal, yaitu mengapa infinity dapat terjadi sebagai ketinggian / lebar dan fakta bahwa Anda tidak dapat mengandalkan pengembalian yang tersediaSize dari MeasureOverride .
Aidan
StackPanel di dalam Grid memecahkan kebutuhannya yang biasa dengan mudah. Bit bawah bisa dimasukkan ke dalam ScrollViewer, jika perlu. Saya sudah melakukan WPF sejak 2006 dan hanya sekali perlu melakukan panel kustom. Saya tidak berpikir itu ide yang baik untuk mendorong kompleksitas ekstra.
Chris Bordeman
@ ChrisBordeman Saya tidak yakin saya mengerti bagaimana tumpukan panel di dalam jaringan menyelesaikan masalah. Idenya adalah untuk memiliki satu atau lebih elemen anak dalam bentangan panel tumpukan untuk mengisi ruang yang tersedia. Menempatkan panel tumpukan di dalam kisi tidak membuatnya berhasil, bukan?
Caleb Vear
61

Metode alternatif adalah menggunakan Grid dengan satu kolom dan n baris. Tetapkan semua ketinggian baris Auto, dan tinggi baris paling bawah ke 1*.

Saya lebih suka metode ini karena saya telah menemukan Grids memiliki kinerja tata letak yang lebih baik daripada DockPanels, StackPanels, dan WrapPanels. Tetapi kecuali jika Anda menggunakannya di ItemTemplate (di mana tata letak sedang dilakukan untuk sejumlah besar item), Anda mungkin tidak akan pernah melihat.

rcabr
sumber
1
bagi saya solusi terbaik. dengan ini dimungkinkan untuk mendefinisikan lebih dari satu baris yang tumbuh
niyou
18

Anda dapat menggunakan SpicyTaco.AutoGrid - versi modifikasi dari 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>

Tombol pertama akan diisi.

Anda dapat menginstalnya melalui NuGet:

Install-Package SpicyTaco.AutoGrid

Saya sarankan untuk melihat SpicyTaco.AutoGrid . Ini sangat berguna untuk formulir di WPF bukan DockPanel, StackPaneldan Griddan menyelesaikan masalah dengan peregangan sangat mudah dan anggun. Lihat saja readme di GitHub.

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

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

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