I know how to do it in code, but can this be done in 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; } } }
You can't do it directly in Xaml but you can use this Attached Behavior. (The Width will be visible in the Designer)
<ComboBox behaviors:ComboBoxWidthFromItemsBehavior.ComboBoxWidthFromItems="True"> <ComboBoxItem Content="Short"/> <ComboBoxItem Content="Medium Long"/> <ComboBoxItem Content="Min"/> </ComboBox>
The Attached Behavior ComboBoxWidthFromItemsProperty
public static class ComboBoxWidthFromItemsBehavior { public static readonly DependencyProperty ComboBoxWidthFromItemsProperty = DependencyProperty.RegisterAttached ( "ComboBoxWidthFromItems", typeof(bool), typeof(ComboBoxWidthFromItemsBehavior), new UIPropertyMetadata(false, OnComboBoxWidthFromItemsPropertyChanged) ); public static bool GetComboBoxWidthFromItems(DependencyObject obj) { return (bool)obj.GetValue(ComboBoxWidthFromItemsProperty); } public static void SetComboBoxWidthFromItems(DependencyObject obj, bool value) { obj.SetValue(ComboBoxWidthFromItemsProperty, value); } private static void OnComboBoxWidthFromItemsPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e) { ComboBox comboBox = dpo as ComboBox; if (comboBox != null) { if ((bool)e.NewValue == true) { comboBox.Loaded += OnComboBoxLoaded; } else { comboBox.Loaded -= OnComboBoxLoaded; } } } private static void OnComboBoxLoaded(object sender, RoutedEventArgs e) { ComboBox comboBox = sender as ComboBox; Action action = () => { comboBox.SetWidthFromItems(); }; comboBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle); } }
What it does is that it calls an extension method for ComboBox called SetWidthFromItems which (invisibly) expands and collapses itself and then calculates the Width based on the generated ComboBoxItems. (IExpandCollapseProvider requires a reference to UIAutomationProvider.dll)
Then extension method SetWidthFromItems
public static class ComboBoxExtensionMethods { public static void SetWidthFromItems(this ComboBox comboBox) { double comboBoxWidth = 19;// comboBox.DesiredSize.Width; // Create the peer and provider to expand the comboBox in code behind. ComboBoxAutomationPeer peer = new ComboBoxAutomationPeer(comboBox); IExpandCollapseProvider provider = (IExpandCollapseProvider)peer.GetPattern(PatternInterface.ExpandCollapse); EventHandler eventHandler = null; eventHandler = new EventHandler(delegate { if (comboBox.IsDropDownOpen && comboBox.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { double width = 0; foreach (var item in comboBox.Items) { ComboBoxItem comboBoxItem = comboBox.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem; comboBoxItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); if (comboBoxItem.DesiredSize.Width > width) { width = comboBoxItem.DesiredSize.Width; } } comboBox.Width = comboBoxWidth + width; // Remove the event handler. comboBox.ItemContainerGenerator.StatusChanged -= eventHandler; comboBox.DropDownOpened -= eventHandler; provider.Collapse(); } }); comboBox.ItemContainerGenerator.StatusChanged += eventHandler; comboBox.DropDownOpened += eventHandler; // Expand the comboBox to generate all its ComboBoxItem's. provider.Expand(); } }
This extension method also provides to ability to call
comboBox.SetWidthFromItems();
in code behind (e.g in the ComboBox.Loaded event)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With