Ich weiß, wie es in Code gemacht wird, aber kann dies in XAML gemacht werden?
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;
}
}
}
Antworten:
Dies kann in XAML nicht sein ohne:
Der Grund dafür ist, dass die Standard-ComboBox-ControlTemplates, auf die ich gestoßen bin (Aero, Luna usw.), den ItemsPresenter in einem Popup verschachteln. Dies bedeutet, dass das Layout dieser Elemente verschoben wird, bis sie tatsächlich sichtbar gemacht werden.
Eine einfache Möglichkeit, dies zu testen, besteht darin, die Standard-ControlTemplate so zu ändern, dass die Mindestbreite des äußersten Containers (es ist ein Raster für Aero und Luna) an die tatsächliche Breite von PART_Popup gebunden wird. Sie können die ComboBox automatisch ihre Breite synchronisieren lassen, wenn Sie auf die Drop-Schaltfläche klicken, jedoch nicht vorher.
Also , wenn Sie einen Measure Betrieb im Layout - System zwingen können (die Sie können durch Hinzufügen einer zweite Steuer tun), glaube ich nicht , es kann getan werden.
Wie immer bin ich offen für eine kurze, elegante Lösung - aber in diesem Fall sind Code-Behind- oder Dual-Control / ControlTemplate-Hacks die einzigen Lösungen, die ich gesehen habe.
quelle
Sie können dies nicht direkt in Xaml tun, aber Sie können dieses angehängte Verhalten verwenden. (Die Breite wird im Designer angezeigt.)
Das angehängte Verhalten ComboBoxWidthFromItemsProperty
Es ruft eine Erweiterungsmethode für ComboBox namens SetWidthFromItems auf, die sich (unsichtbar) erweitert und reduziert und dann die Breite basierend auf den generierten ComboBoxItems berechnet. (IExpandCollapseProvider erfordert einen Verweis auf UIAutomationProvider.dll)
Dann Erweiterungsmethode SetWidthFromItems
Diese Erweiterungsmethode bietet auch die Möglichkeit zum Aufrufen
im Code dahinter (zB im ComboBox.Loaded-Ereignis)
quelle
SetWidthFromItems
mithilfe einer Aktion / eines Delegaten und eines BeginInvoke mit einer Leerlaufpriorität (wie im Ereignis Loaded) asynchron zu machen . Auf diese Weise wird keine Maßnahme durchgeführt, solange die Messge-Pumpe nicht leer ist, und daher tritt keine Nachrichtenverschachtelung aufdouble comboBoxWidth = 19;
in Ihrem Code verwandt mitSystemParameters.VerticalScrollBarWidth
?Ja, dieser ist ein bisschen böse.
Was ich in der Vergangenheit getan habe, ist, der ControlTemplate ein verstecktes Listenfeld hinzuzufügen (dessen Elementcontainerpanel auf ein Raster eingestellt ist), in dem jedes Element gleichzeitig angezeigt wird, dessen Sichtbarkeit jedoch auf ausgeblendet eingestellt ist.
Ich würde mich freuen, von besseren Ideen zu hören, die nicht auf schrecklichem Code-Behind beruhen oder von Ihrer Ansicht, dass sie verstehen müssen, dass ein anderes Steuerelement verwendet werden muss, um die Breite zur Unterstützung der Grafik bereitzustellen (igitt!).
quelle
Basierend auf den anderen Antworten oben, hier ist meine Version:
HorizontalAlignment = "Left" stoppt die Steuerelemente mit der vollen Breite des enthaltenen Steuerelements. Höhe = "0" verbirgt die Gegenstandskontrolle.
Margin = "15,0" ermöglicht zusätzliches Chrom um Combo-Box-Elemente (leider nicht chromunabhängig).
quelle
Am Ende hatte ich eine "gute" Lösung für dieses Problem, bei der das Kombinationsfeld niemals unter die größte Größe schrumpfte, die es enthielt, ähnlich wie beim alten WinForms AutoSizeMode = GrowOnly.
Ich habe dies mit einem benutzerdefinierten Wertekonverter getan:
Dann konfiguriere ich das Kombinationsfeld in XAML wie folgt:
Beachten Sie, dass Sie für jedes Kombinationsfeld eine separate Instanz des GrowConverter benötigen, es sei denn, Sie möchten natürlich, dass eine Reihe von Instanzen zusammen dimensioniert wird, ähnlich wie bei der SharedSizeScope-Funktion des Grids.
quelle
Eine Fortsetzung von Maleaks Antwort: Diese Implementierung hat mir so gut gefallen, dass ich ein tatsächliches Verhalten dafür geschrieben habe. Natürlich benötigen Sie das Blend SDK, damit Sie auf System.Windows.Interactivity verweisen können.
XAML:
Code:
quelle
provider.Expand()
wirft eineElementNotEnabledException
. Wenn die ComboBox nicht aktiviert ist, weil ein Elternteil deaktiviert ist, kann die ComboBox erst nach Abschluss der Messung vorübergehend aktiviert werden.Stellen Sie eine Listbox mit demselben Inhalt hinter die Dropbox. Erzwingen Sie dann die korrekte Höhe mit einer Bindung wie dieser:
quelle
In meinem Fall schien ein viel einfacherer Weg den Trick zu tun, ich habe nur ein zusätzliches stackPanel verwendet, um die Combobox zu verpacken.
(arbeitete im Visual Studio 2008)
quelle
Eine alternative Lösung zur Top-Antwort besteht darin, das Popup selbst zu messen, anstatt alle Elemente zu messen . Etwas einfachere
SetWidthFromItems()
Implementierung:funktioniert auch bei Behinderten
ComboBox
.quelle
Ich habe selbst nach der Antwort gesucht, als ich auf die
UpdateLayout()
Methode gestoßen bin, die jederUIElement
hat.Zum Glück ist es jetzt sehr einfach!
Rufen
ComboBox1.Updatelayout();
Sie einfach an, nachdem Sie das eingestellt oder geändert habenItemSource
.quelle
Alun Harfords Ansatz in der Praxis:
quelle
Dadurch bleibt die Breite auf dem breitesten Element, jedoch nur nach einmaligem Öffnen des Kombinationsfelds.
quelle