Conduit
Conduit

Reputation: 2735

Listbox with auto-sizing, horizontal scroll bar

I am attempting to use the following code to find the width of the longest item in a listbox and then alter the HorizontalExtent property of the listbox to fit the item within the bounds of the horizontal scroll bar:

Graphics widthFinder = listBox_Transactions.CreateGraphics();
int needScrollWidth = 0; int checkVal = 0;
for (int i = 0; i < listBox_Transactions.Items.Count; i++)
{
    checkVal = (int)widthFinder.MeasureString(listBox_Transactions.Items[i].ToString(), listBox_Transactions.Font).Width + 1;
    if (needScrollWidth < checkVal)
    { needScrollWidth = checkVal; }
}

listBox_Transactions.HorizontalScrollbar = true;
listBox_Transactions.HorizontalExtent = needScrollWidth;
listBox_Transactions.Invalidate();

The code seems to work as expected, with the exception that widthFinder.MeasureString(listBox_Transactions.Items[i].ToString(), listBox_Transactions.Font).Width always returns 164. I've searched for reasons this could be happening, but haven't found any. Any ideas?

Upvotes: 1

Views: 1490

Answers (1)

Martin McGirk
Martin McGirk

Reputation: 411

It's hard to know for sure, and sadly as I write this I don't have the reputation required to ask for clarification as a comment, however...

I've tried your code and it works fine for me. All I can think of is that if you're using a different DisplayMember and ValueMember then I'm assuming that you're adding objects to the Items property rather than simple types. In that case your

listBox_Transactions.Items[i].ToString()

will end up providing you with the name of the object, rather than the value you were hoping for.

Suppose I have a List of class Foo and add it to your listbox

List<Foo> fooList = new List<Foo>();
fooList.Add(new Foo() { Bar = 1 });
fooList.Add(new Foo() { Bar = 2 });
fooList.Add(new Foo() { Bar = 3 });
fooList.Add(new Foo() { Bar = 45 });

listBox_Transactions.Items.AddRange(fooList.ToArray());
listBox_Transactions.DisplayMember = "Bar";
listBox_Transactions.ValueMember = "Bar";

then in your code when I get to

listBox_Transactions.Items[i].ToString()

I will get the value

"Namespace.Foo"

Rather than the value I was meaning to get. This would therefore always end up giving the same string length.

To fix this, cast back to your object type in the above code like so:

((Foo)listBox_Transactions.Items[i]).Bar.ToString()

Hopefully this will help.

Upvotes: 1

Related Questions