Reputation: 10055
I have a custom control based on CheckedListBox
public CustomCheckedListBox : CheckedListBox
{
public void AddItems(CustomCollection MyCollection)
{
foreach(var C in MyCollection.Items)
{
// Some logic is here to determine if an item should be added.
this.Items.Add(C); // The C object has a string overload
}
}
}
When this control is used with some long text the horizontal scroll bar doesn't seem to be sized correctly. When i scroll to the right the text is cut off.
If i clear the Items collection and write its contents again after the control is already loaded then the horizontal scroll bar is sized correctly.
Any idea what could be causing this?
I have the same issue if just using the standard CheckedListBox.
On the red line there about about 5 characters missing at the end. It happens with all character types.
Upvotes: 0
Views: 1789
Reputation: 81
I have fought with this for some time now. I found a solution (I can't find it again to give credit) where I change the HorizontalExtent
based on the strings length combined with CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.CheckedNormal).Width
The full method look like this but there are some improvements to the check state that can be made.
public void SetHorizontalExtent()
{
// Create a Graphics object to use when determining the size of the largest item in the ListBox.
Graphics g = cbl_causeCodes.CreateGraphics();
int maxSize = 0;
foreach (var item in cbl_causeCodes.Items)
{
//CheckBoxState state = causeCodes.Contains(config.Value) ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal;
int hzSize = (int)(g.MeasureString(item.ToString(), cbl_causeCodes.Font).Width);
hzSize += CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.CheckedNormal).Width;
if (hzSize > maxSize)
maxSize = hzSize;
}
cbl_causeCodes.HorizontalExtent = maxSize;
}
Upvotes: 0
Reputation: 205859
There seems to be a bug in the ListBox
implementation, using different methods for item text width measurement, which is causing the behavior you are experiencing.
To fix that, you can use the following helper (warning: uses ListBox
private implementation members)
using System;
using System.Linq.Expressions;
using System.Windows.Forms;
namespace Samples
{
public static class ListBoxUtils
{
public static void UpdateHorizontalScrollbar(this ListBox target)
{
updateHorizontalScrollbarFunc(target);
}
private static readonly Action<ListBox> updateHorizontalScrollbarFunc = CreateUpdateScrollbarFunc();
private static Action<ListBox> CreateUpdateScrollbarFunc()
{
var target = Expression.Parameter(typeof(ListBox), "target");
var body = Expression.Block(
Expression.Assign(Expression.Field(target, "maxWidth"), Expression.Constant(-1)),
Expression.Call(target, "UpdateHorizontalExtent", null)
);
var lambda = Expression.Lambda<Action<ListBox>>(body, target);
return lambda.Compile();
}
}
}
After modifying items collection, just call
listBox.UpdateHorizontalScrollbar();
Upvotes: 0