Winforms DotNet ListBox items to word wrap if content string width is bigger than ListBox width?
Asked Answered
B

4

17

Ehm, umm, this means some lines should be two-lined in size. My boss think this is more simple solution, than limit displayed text to fit width and don't like horizontal scroll bar >_<

Billye answered 12/7, 2013 at 11:10 Comment(0)
B
40
lst.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
lst.MeasureItem += lst_MeasureItem;
lst.DrawItem += lst_DrawItem;

private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
    e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}

private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    e.DrawFocusRectangle();
    e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}
Billye answered 14/7, 2013 at 14:9 Comment(13)
Love it. One minor thing though. When I databind a custom class, the DisplayMember gets wiped and I can't seem to reset it. Any tips?Burly
@BillSambrone - Sorry, but I don't use databind and never meet same problem and don't know how to solve.Liberati
@AycanYaşıt : totaly agreeCriswell
@Kosmos Seems that the ListBox caches the items height, what is good. The problem is that if the ListBox is resized it don't recalculates the height! I'm trying someway to clean the cache of items height without removing and adding then, in the resize, but I don't find any method for that. At least documented.Brittaniebrittany
@DiegoCNascimento - I used ListBox.Refresh method in resize handler for that.Liberati
@Kosmos Refresh does not work, it will just add all the area of the ListBox to next Paint event, but does not calculate the new items height.Brittaniebrittany
@DiegoCNascimento - I don't know why, but for me it worked fine. I used Form's resize event and called list box's Refresh method. I don't know why you telling it's not working. Refresh causes control to redraw and when it redraws it should run the calculation code again.Liberati
@Kosmos what version of .Net are you using (even trough the ListBox is a native windows control)? It don't raise the MeasureItem event, you can search for the same question in other places. Anyway I found a way to change item heightBrittaniebrittany
Also take a look at that Unfortunately, the MeasureItem event only happens when the handle gets created in this answer.Brittaniebrittany
@DiegoCNascimento - Meh, I tested it and finally understand what you meant. I though that text stays the same after resizing (no updates), but the text changes according to space available, while item height no. Well..., currently I don't know what to do.Liberati
@Kosmos Yes, that's it. Putting it, the item height is dependent on the item width, being the item width dependent on the control client area width. I come with a solution. The ListBox that is a native windows control, has way to set item height, so you can call it with "Windows API". Also, I make a call to the measure item, for each item and called the "Windows API", so that it worked. There's only a glitch when the scroll bar gets show or hidden. Thanks!Brittaniebrittany
@BillSambrone If you use a custom class, you need to replace "lst.Items[e.Index].ToString()" to "((CustomClass)lst.Items[e.Index]).YourMethodShowTheClass".Auricula
Worked like a charm.Alston
D
2
private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
    e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}

private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    e.DrawFocusRectangle();
    e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}

To get the right display member to show up when data binding, replace

lst.Items[e.Index].ToString()

with a casted version of the property. So if your binding source is class object Car it would look like

((Car)lst.Items[e.Index]).YourDisplayProperty

Then the above functions can appropriately measure the string and draw it. :)

Disband answered 16/10, 2014 at 15:47 Comment(0)
U
1

Helpful link

Check out this answer. It overrides the template of the listbox with a textblock which wraps the text. Hope it's useful. To solve your problem I think you shold add : ScrollViewer.HorizontalScrollBarVisibility="Disabled" . Found it here

Unhallowed answered 12/7, 2013 at 11:17 Comment(1)
Thanks, but I use win forms :(Liberati
A
0

To make binding correct, be sure to add check "lst.Items.Count > 0" to lst_MeasureItem function. Here is my example:

 if (lst.Items.Count > 0)
 {
    e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
 }

Everything else seems to work nicely after that.

Arid answered 29/1, 2015 at 18:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.