Saya tahu bagaimana melakukannya dalam kode, tetapi bisakah ini dilakukan di XAML?
Window1.xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox Name="ComboBox1" HorizontalAlignment="Left" VerticalAlignment="Top">
<ComboBoxItem>ComboBoxItem1</ComboBoxItem>
<ComboBoxItem>ComboBoxItem2</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
Window1.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
double width = 0;
foreach (ComboBoxItem item in ComboBox1.Items)
{
item.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
if (item.DesiredSize.Width > width)
width = item.DesiredSize.Width;
}
ComboBox1.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
ComboBox1.Width = ComboBox1.DesiredSize.Width + width;
}
}
}
Jawaban:
Ini tidak bisa di XAML tanpa:
Alasan untuk ini adalah bahwa ComboBox ControlTemplates default yang saya temui (Aero, Luna, dll.) Semua menumpuk ItemsPresenter dalam Popup. Ini berarti bahwa tata letak item-item ini ditangguhkan hingga benar-benar terlihat.
Cara mudah untuk mengujinya adalah dengan memodifikasi ControlTemplate default untuk mengikat MinWidth dari container terluar (ini adalah Grid untuk Aero dan Luna) ke ActualWidth dari PART_Popup. Anda akan dapat membuat ComboBox secara otomatis menyinkronkan lebarnya ketika Anda mengklik tombol drop, tetapi tidak sebelumnya.
Jadi, kecuali Anda dapat memaksa operasi Ukur dalam sistem tata letak (yang dapat Anda lakukan dengan menambahkan kontrol kedua), saya rasa itu tidak bisa dilakukan.
Seperti biasa, saya terbuka untuk solusi singkat dan elegan - tetapi dalam kasus ini hacks code-behind atau dual-control / ControlTemplate adalah satu-satunya solusi yang pernah saya lihat.
sumber
Anda tidak dapat melakukannya secara langsung di Xaml tetapi Anda dapat menggunakan Perilaku Terlampir ini. (Lebar akan terlihat di Desainer)
The Attached Behavior ComboBoxWidthFromItemsProperty
Apa yang dilakukannya adalah memanggil metode ekstensi untuk ComboBox yang disebut SetWidthFromItems yang (tidak terlihat) mengembang dan menciut sendiri dan kemudian menghitung Lebar berdasarkan ComboBoxItems yang dihasilkan. (IExpandCollapseProvider membutuhkan referensi ke UIAutomationProvider.dll)
Kemudian metode ekstensi SetWidthFromItems
Metode ekstensi ini juga menyediakan kemampuan untuk menelepon
dalam kode di belakang (misalnya di acara ComboBox.Loaded)
sumber
SetWidthFromItems
asynchronous saya menggunakan aksi / delegasi dan BeginInvoke dengan prioritas Idle (seperti yang dilakukan dalam acara Loaded). Dengan cara ini, tidak ada pengukuran yang akan dilakukan saat pompa pesan tidak kosong, dan dengan demikian, tidak akan terjadi interleaving pesandouble comboBoxWidth = 19;
dalam kode Anda berhubungan denganSystemParameters.VerticalScrollBarWidth
?Ya, yang ini agak buruk.
Apa yang telah saya lakukan di masa lalu adalah menambahkan ke dalam ControlTemplate kotak daftar tersembunyi (dengan itemscontainerpanel diatur ke kisi) yang menampilkan setiap item pada saat yang sama tetapi dengan visibilitas diatur ke tersembunyi.
Saya akan senang mendengar ide yang lebih baik yang tidak bergantung pada kode di belakang yang mengerikan atau pandangan Anda harus memahami bahwa itu perlu menggunakan kontrol yang berbeda untuk memberikan lebar untuk mendukung visual (yuck!).
sumber
Berdasarkan jawaban lain di atas, inilah versi saya:
HorizontalAlignment = "Left" menghentikan kontrol menggunakan lebar penuh dari kontrol penampung. Height = "0" menyembunyikan kontrol item.
Margin = "15,0" memungkinkan penambahan chrome di sekitar item kotak kombo (sayangnya, bukan chrome agnostik).
sumber
Saya akhirnya mendapatkan solusi yang "cukup baik" untuk masalah ini yaitu membuat kotak kombo tidak pernah menyusut di bawah ukuran terbesar yang dimilikinya, mirip dengan WinForms AutoSizeMode = GrowOnly yang lama.
Cara saya melakukan ini adalah dengan konverter nilai khusus:
Kemudian saya mengkonfigurasi kotak kombo di XAML seperti ini:
Perhatikan bahwa dengan ini Anda memerlukan contoh terpisah dari GrowConverter untuk setiap kotak kombo, kecuali tentu saja Anda ingin satu set dari mereka untuk ukuran bersama, mirip dengan fitur SharedSizeScope Grid.
sumber
Tindak lanjut dari jawaban Maleak: Saya sangat menyukai penerapan itu, saya menulis Perilaku yang sebenarnya untuk itu. Jelas Anda membutuhkan Blend SDK sehingga Anda dapat mereferensikan System.Windows.Interactivity.
XAML:
Kode:
sumber
provider.Expand()
melemparElementNotEnabledException
. Ketika Kotak Kombo tidak diaktifkan, karena orang tua dinonaktifkan, maka bahkan tidak mungkin untuk mengaktifkan Kotak Kombo untuk sementara sampai pengukuran selesai.Letakkan kotak daftar yang berisi konten yang sama di belakang dropbox. Kemudian tegakkan ketinggian yang benar dengan beberapa pengikatan seperti ini:
sumber
Dalam kasus saya cara yang jauh lebih sederhana tampaknya melakukan trik, saya hanya menggunakan stackPanel ekstra untuk membungkus kotak kombo.
(bekerja di studio visual 2008)
sumber
Solusi alternatif untuk jawaban teratas adalah Mengukur Popup itu sendiri daripada mengukur semua item. Memberikan
SetWidthFromItems()
implementasi yang sedikit lebih sederhana :bekerja pada orang-orang cacat
ComboBox
juga.sumber
Saya sendiri sedang mencari jawabannya, ketika saya menemukan
UpdateLayout()
metode yangUIElement
dimiliki setiap orang .Ini sangat sederhana sekarang, untungnya!
Panggil saja
ComboBox1.Updatelayout();
setelah Anda menyetel atau memodifikasi fileItemSource
.sumber
Pendekatan Alun Harford, dalam praktiknya:
sumber
Ini membuat lebar menjadi elemen terluas tetapi hanya setelah membuka kotak kombo sekali.
sumber