CathalMF
CathalMF

Reputation: 10055

CheckedListBox Horizontal Scroll bar is not allowing me to see all text

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

Answers (2)

Jakobitz
Jakobitz

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

Ivan Stoev
Ivan Stoev

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

Related Questions