Bagaimana cara mendapatkan kontrol dalam WPF untuk mengisi ruang yang tersedia?

304

Beberapa kontrol WPF (seperti Button) tampaknya dengan senang hati menghabiskan semua ruang yang tersedia dalam wadahnya jika Anda tidak menentukan ketinggian yang harus dimiliki.

Dan beberapa, seperti yang perlu saya gunakan sekarang, (multiline) TextBoxdan yang ListBoxtampak lebih khawatir hanya mengambil ruang yang diperlukan agar sesuai dengan isinya, dan tidak lebih.

Jika Anda menempatkan orang-orang ini di sel dalam UniformGrid, mereka akan berkembang agar sesuai dengan ruang yang tersedia. Namun, UniformGridcontoh tidak tepat untuk semua situasi. Bagaimana jika Anda memiliki kisi dengan beberapa baris diatur ke * tinggi untuk membagi ketinggian antara dirinya dan baris * lainnya? Bagaimana jika Anda memiliki StackPaneldan Anda memiliki Label, Listdan Button, bagaimana Anda bisa mendapatkan daftar untuk mengambil semua ruang yang tidak dimakan oleh label dan tombol?

Saya akan berpikir ini benar-benar akan menjadi persyaratan tata letak dasar, tapi saya tidak tahu bagaimana cara agar mereka mengisi ruang yang mereka bisa (menempatkan mereka di DockPaneldan mengaturnya untuk mengisi juga tidak berfungsi, tampaknya, karena yang DockPanelhanya membutuhkan ruang yang diperlukan oleh subcontrols nya).

Sebuah GUI resizable akan cukup mengerikan jika Anda harus bermain dengan Height, Width, MinHeight, MinWidthdll

Bisakah Anda mengikat Heightdan Widthproperti Anda ke sel grid yang Anda tempati? Atau adakah cara lain untuk melakukan ini?

Rune Jacobsen
sumber
1
UniformGrid luar biasa, tag goto standar baru saya. Saya menyukai kesederhanaan Stackpanels (mengingatkan saya pada div) tetapi Uniform Grid melakukan apa yang saya butuhkan.
Terrance
UniformGrid Kembali. Penekanannya pada Seragam. Tampaknya Anda tidak dapat mengatur lebar kolom tanpa ketinggian baris. Ini hanya cocok jika setiap konten memiliki ukuran yang sama. Saya mengganti StackPanel saya dengan Grid, dan Stretch kemudian bekerja seperti yang saya harapkan.
pdschuller
Artikel ini membantu saya meregangkan kotak teks.
jpaugh

Jawaban:

162

Setiap kontrol yang berasal dari Panelmengimplementasikan logika tata letak berbeda dilakukan di Measure()dan Arrange():

  • Measure() menentukan ukuran panel dan masing-masing anak-anaknya
  • Arrange() menentukan persegi panjang di mana setiap kontrol dirender

Anak terakhir dari DockPanelmengisi ruang yang tersisa. Anda dapat menonaktifkan perilaku ini dengan menyetel LastChildproperti ke false.

Mereka StackPanelmeminta setiap anak untuk ukuran yang diinginkan dan kemudian menumpuknya. Panel tumpukan memanggil Measure()setiap anak, dengan ukuran yang tersedia Infinitydan kemudian menggunakan ukuran yang diinginkan anak tersebut.

A Gridmenempati semua ruang yang tersedia, namun, itu akan mengatur setiap anak ke ukuran yang diinginkan dan kemudian menempatkannya di dalam sel.

Anda bisa menerapkan logika tata letak Anda sendiri dengan mengambil dari Paneldan kemudian mengesampingkan MeasureOverride()dan ArrangeOverride().

Lihat artikel ini untuk contoh sederhana.

pengguna3837
sumber
8
Tautan sekarang mati
user3690202
6
@ user3690202 Archive.org adalah teman Anda. Tautan dihidupkan kembali.
ruffin
4
Topiknya masih ada di MSDN, tetapi tautannya berubah menjadi ini: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/…
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: ini adalah kunci yang hilang untuk pemahaman saya. Saya selalu berpikir bahwa elemen tanpa Dock eksplisit memenuhi ruang.
Terlihat
238

Ada juga beberapa properti yang bisa Anda atur untuk memaksa kontrol untuk mengisi ruang yang tersedia ketika tidak akan melakukannya. Misalnya, Anda dapat mengatakan:

HorizontalContentAlignment="Stretch"

... untuk memaksa konten kontrol untuk meregang secara horizontal. Atau Anda bisa mengatakan:

HorizontalAlignment="Stretch"

... untuk memaksa kontrol itu sendiri untuk meregangkan secara horizontal untuk mengisi induknya.

Matt Hamilton
sumber
88
Panel paling terkenal yang disebutkan dalam semua kasus ini adalah StackPanel. Ini tidak mengandung properti ContentAlignment dan mengatur anak-anaknya ke Stretch tidak akan berpengaruh di dalam kisi berukuran bintang. Sangat membuat frustrasi. Hampir seolah-olah StackPanel adalah wadah pertama yang ditulis oleh tim WPF dan menderita karena itu.
Brent Schooley
4
@Brent - ahh! Saya telah terjebak dalam upaya untuk mendapatkan isi stackpanel saya dengan benar. Terima kasih! Saya pikir itu hanya sesuatu yang saya lakukan salah.
Ashley Grenon
8
@townsean Stack panel sangat terbatas, Anda bisa mendapatkan perilaku serupa dengan peregangan menggunakan UniformGrid dan mengatur baik Baris atau Kolom ke 0
ForbesLindesay
2
@ Tuskan360 UniformGrid hanya memungkinkan sel berukuran sama. Saya menggunakan Grid pada akhirnya, sepertinya berhasil. Mengganggu bagaimana StackPanel tidak melakukan apa yang tampaknya dirancang untuk itu.
TarkaDaal
4
@TarkaDaal ya, UniformGrid jika semuanya memiliki ukuran yang sama, Kisi jika Anda ingin menentukan ukuran relatif kompleks, susun panel hanya berdasarkan ukuran konten dan abaikan berapa banyak ruang yang tersedia.
ForbesLindesay
18

Yah, saya menemukan jawabannya sendiri, tepat setelah memposting, yang merupakan cara yang paling memalukan. :)

Tampaknya setiap anggota StackPanel hanya akan mengisi ukuran minimum yang diminta.

Di DockPanel, saya telah merapat hal-hal dengan urutan yang salah. Jika TextBox atau ListBox adalah satu-satunya item yang di-dock tanpa sejajar, atau jika itu adalah yang terakhir ditambahkan, mereka AKAN mengisi ruang yang tersisa seperti yang diinginkan.

Saya ingin melihat metode penanganan yang lebih elegan, tetapi itu akan berhasil.

Rune Jacobsen
sumber
Saya hanya ingin menunjukkan (pada pertanyaan lama ini!) Bahwa "tanpa keberpihakan" adalah ungkapan kunci di sini, setidaknya itu untuk saya.
MikeBaz - MSFT
4

Gunakan properti tata letak HorizontalAlignment dan VertikalAlignment . Mereka mengontrol bagaimana suatu elemen menggunakan ruang yang dimilikinya di dalam induknya ketika lebih banyak ruang tersedia daripada yang dibutuhkan oleh elemen tersebut.

Lebar StackPanel, misalnya, akan selebar elemen terluas yang dikandungnya. Jadi, semua elemen yang lebih sempit memiliki sedikit ruang berlebih. Properti pelurusan mengontrol apa yang dilakukan elemen anak dengan ruang ekstra.

Nilai default untuk kedua properti adalah Peregangan, sehingga elemen anak direntangkan untuk mengisi semua ruang yang tersedia. Opsi tambahan termasuk Kiri, Tengah dan Kanan untuk Perataan Horizontal dan Atas, Tengah dan Bawah untuk Perataan Vertikal .

urini
sumber
31
Jika ini selalu benar, pertanyaan awal tidak akan ditanyakan. Ambil, misalnya, StackPanel horizontal dengan Label dan TextBox. Ada ruang ekstra di sebelah kanan TextBox. TextBox diatur ke Lebar otomatis. Pengaturan Stretch untuk HorizontalAlignment tidak akan membuat TextBox mengisi ruang yang tersisa.
Brent Schooley
Tidak ada yang selalu benar tetapi jawaban ini berfungsi untuk kebutuhan saya: DockPanel, Image.
alehro