Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a combobox size to the maximum width of its content?

Tags:

.net

combobox

wpf

I have this ComboBox

<ComboBox ItemsSource="{Binding Path=Foo.Bars}"/>

Can I set the size of the combobox to the width of its widest item?

For example, if the contents are:

John Doe
Jane Mary
Josh

The length would be equal to the length of Jane Mary.

Also, in this case the contents are not expected to change after initialization

like image 571
Louis Rhys Avatar asked Sep 13 '11 09:09

Louis Rhys


People also ask

How do I change the width of a combobox in C#?

// Set the size of the combobox mybox. Size = new Size(216, 26);

How do you change the size of a combobox in Python?

Simple, add font attribute. For eg. ttk. Combobox(root, values=[1, 2, 3, 4, 5], state="readonly", width=1, font="Verdana 12 bold") .


2 Answers

What you can do is make a converter that would return the longest length of one your object property. You can implement the converter like this:

public class LongestListObjectToIntConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is IEnumerable<FooBar>)
        {
            IEnumerable<FooBar> list = (IEnumerable<FooBar>)value;

            return list.Max(bar => bar.FullName.Length);
        }

        // Default value to return
        return 100;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And then simply bind the Width property of your ComboBox by provinding the list as the Path binding and your converter as a value converter.

<Window.Resources>
    <conv:LongestListObjectToIntConverter x:Key=converter/>
</Windows.Resources>

    ...

<ComboBox ItemsSource="{Binding Path=Foo.Bars}" Width="{Binding Path=Foo.Bars, Converter={StaticResource converter}}"/>

This way, even if your collection changes and this changes are not notified, the ComboBox would resize depending on the longest word.

Another interesting idea would be to make a self binding on Width and grab the actual combobox in the converter to then inspect the displayed value, that would be even better I think.

The advantage of this solution is that uses no code-behind and is easily reusable. You can find more information on ValueConverters here: http://www.wpftutorial.net/ValueConverters.html

like image 89
Ucodia Avatar answered Nov 01 '22 15:11

Ucodia


You can write converter like this

 public class ComboBoxToMaxItemWidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double maxWidth = 0;
        ComboBox cb = (ComboBox)value;
        foreach (var item in cb.Items)
        {
            ComboBoxItem cbItem = (ComboBoxItem)cb.ItemContainerGenerator.ContainerFromItem(item);
            if (cbItem.ActualWidth > maxWidth)
                maxWidth = cbItem.ActualWidth;
        }
        return maxWidth;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And use it

<ComboBox ItemsSource="{Binding Path=Foo.Bars}" Width={Binding RelativeSource={RelativeSource Self}, Converter={StaticResource comboBoxToMaxItemWidthConverter }/>

Hope this helps

like image 20
Arsen Mkrtchyan Avatar answered Nov 01 '22 15:11

Arsen Mkrtchyan