Wiem, jak to zrobić w kodzie, ale czy można to zrobić w języku 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;
}
}
}
Odpowiedzi:
To nie może być w XAML bez:
Powodem tego jest to, że domyślne ComboBox ControlTemplates, z którymi się spotkałem (Aero, Luna itp.), Wszystkie zagnieżdżają ItemsPresenter w Popup. Oznacza to, że układ tych elementów jest odroczony, dopóki nie staną się widoczne.
Łatwym sposobem na przetestowanie tego jest zmodyfikowanie domyślnego ControlTemplate, aby powiązać MinWidth najbardziej zewnętrznego kontenera (jest to Siatka zarówno dla Aero, jak i Luny) z ActualWidth PART_Popup. Będziesz mógł automatycznie synchronizować ComboBox jego szerokość po kliknięciu przycisku upuść, ale nie wcześniej.
Więc chyba można wymusić działanie środka w systemie układ (którego można zrobić poprzez dodanie drugiego Control), nie sądzę, można to zrobić.
Jak zawsze jestem otwarty na krótkie, eleganckie rozwiązanie - ale w tym przypadku hacki związane z kodem lub podwójną kontrolą / ControlTemplate są jedynymi rozwiązaniami, jakie widziałem.
źródło
Nie możesz tego zrobić bezpośrednio w Xaml, ale możesz użyć tego dołączonego zachowania. (Szerokość będzie widoczna w Projektancie)
Dołączone zachowanie ComboBoxWidthFromItemsProperty
To, co robi, to wywołanie metody rozszerzającej dla ComboBox o nazwie SetWidthFromItems, która (niewidocznie) rozwija się i zwija, a następnie oblicza Width na podstawie wygenerowanych ComboBoxItems. (IExpandCollapseProvider wymaga odwołania do UIAutomationProvider.dll)
Następnie metoda rozszerzenia SetWidthFromItems
Ta metoda rozszerzenia zapewnia również możliwość wywołania
w kodzie za (np. w zdarzeniu ComboBox.Loaded)
źródło
SetWidthFromItems
asynchroniczne ustawienie całej metody przy użyciu akcji / delegata i BeginInvoke z priorytetem Idle (tak jak w przypadku Loaded). W ten sposób żaden pomiar nie zostanie wykonany, gdy pompa wiadomości nie jest pusta, a zatem nie nastąpi przeplatanie wiadomościdouble comboBoxWidth = 19;
w twoim kodzie jest związana zSystemParameters.VerticalScrollBarWidth
?Tak, ten jest trochę paskudny.
W przeszłości dodałem do ControlTemplate ukrytą listę (z itemcontainerpanel ustawioną na siatkę) pokazującą każdy element w tym samym czasie, ale z ich widocznością ustawioną na ukrytą.
Z przyjemnością usłyszę o jakichkolwiek lepszych pomysłach, które nie opierają się na okropnym kodzie lub twoim spojrzeniu, które musi zrozumieć, że musi użyć innej kontrolki, aby zapewnić szerokość do obsługi wizualizacji (fuj!).
źródło
Na podstawie innych odpowiedzi powyżej, oto moja wersja:
HorizontalAlignment = "Left" zatrzymuje kontrolki przy użyciu pełnej szerokości kontrolki zawierającej. Wysokość = „0” ukrywa kontrolę elementów.
Margines = "15,0" pozwala na dodanie dodatkowego chromu dookoła elementów z listy rozwijanej (niestety nie jest on niezależny od chromu).
źródło
Skończyło się na „wystarczająco dobrym” rozwiązaniu tego problemu polegającym na tym, że pole kombi nigdy nie zmniejszyło się poniżej największego posiadanego rozmiaru, podobnie jak w starym WinForms AutoSizeMode = GrowOnly.
Sposób, w jaki to zrobiłem, był z niestandardowym konwerterem wartości:
Następnie konfiguruję pole kombi w XAML w następujący sposób:
Zauważ, że w tym przypadku potrzebujesz oddzielnego wystąpienia GrowConvertera dla każdego pola kombi, chyba że chcesz, aby zestaw ich rozmiaru był razem, podobnie jak funkcja SharedSizeScope sieci Grid.
źródło
Kontynuacja odpowiedzi Maleaka: tak bardzo podobało mi się to wdrożenie, napisałem dla niego rzeczywiste zachowanie. Oczywiście będziesz potrzebować Blend SDK, aby móc odwoływać się do System.Windows.Interactivity.
XAML:
Kod:
źródło
provider.Expand()
rzucaElementNotEnabledException
. Gdy ComboBox nie jest włączony z powodu wyłączenia rodzica, nie jest nawet możliwe tymczasowe włączenie ComboBox do czasu zakończenia pomiaru.Umieść listę zawierającą tę samą zawartość za skrzynką referencyjną. Następnie wymuś poprawną wysokość za pomocą takiego wiązania:
źródło
W moim przypadku o wiele prostszy sposób wydawał się załatwić sprawę, po prostu użyłem dodatkowego panelu stosu do owinięcia combobox.
(pracował w Visual Studio 2008)
źródło
Alternatywnym rozwiązaniem dla pierwszej odpowiedzi jest zmierzenie samego wyskakującego okienka zamiast mierzenia wszystkich elementów. Dając nieco prostszą
SetWidthFromItems()
implementację:działa również na niepełnosprawnych
ComboBox
.źródło
Sam szukałem odpowiedzi, kiedy natrafiłem na
UpdateLayout()
metodę, którą każdyUIElement
ma.Na szczęście jest to teraz bardzo proste!
Po prostu zadzwoń
ComboBox1.Updatelayout();
po ustawieniu lub zmodyfikowaniuItemSource
.źródło
Podejście Aluna Harforda w praktyce:
źródło
Zachowuje to szerokość do najszerszego elementu, ale tylko po jednokrotnym otwarciu pola kombi.
źródło