0

i have a listbox and i would want to display a label displaying:

scrolling through items XXX to XYY of ZZZ.

how do I do this because using SelectedIndex will not be useful, as i would like the label to update even when nothing is selected. (scrolling too, it does not select an item).

update: for example I have 200 items in my listbox. at any one time i can only display only 10 items because of my listbox's height. so the label should read:

displaying items 1 to 10 of 200

or

displaying items 5 to 15 of 200

however i must take into account that there may not be any indices selected because i can simply scroll and not select anything.

BOOnZ
  • 828
  • 2
  • 15
  • 35

3 Answers3

4

You can get the top index value using listbox.TopIndex and the count using listbox.Items.Count but I can't see any way to get the bottom item withotu calculating it from the result of listbox.GetItemHeight() and listbox.ClientSize.Height:

int visibleCount = listBox1.ClientSize.Height / listBox1.ItemHeight;
this.Text = string.Format("{0:d} to {1:d} of {2:d}", listBox1.TopIndex + 1, listBox1.TopIndex + visibleCount, listBox1.Items.Count);

This can be done on a timer as I see no scroll event.

Deanna
  • 23,876
  • 7
  • 71
  • 156
  • ah yes i'm not saying other methods won't work but this provide the fastest solution! thank you! – BOOnZ Nov 04 '11 at 15:39
1

Just use the Scroll event of the ListBox. Oh wait, there isn't one. You can add one:

public class ListBoxEx : ListBox {
  public event EventHandler Scrolling;

  private const int WM_VSCROLL = 0x0115;

  private void OnScrolling() {
    if (Scrolling != null)
      Scrolling(this, new EventArgs());
  }

  protected override void WndProc(ref Message m) {
    base.WndProc(ref m);
    if (m.Msg == WM_VSCROLL)
      OnScrolling();
  }
}

Once you use this, it's just math (refactor as needed):

private void listBoxEx1_Resize(object sender, EventArgs e) {
  DisplayRange();
}

private void listBoxEx1_Scrolling(object sender, EventArgs e) {
  DisplayRange();
}

private void DisplayRange() {
  int numFrom = listBoxEx1.TopIndex + 1;
  int numTo = numFrom + (listBoxEx1.ClientSize.Height / listBoxEx1.ItemHeight) - 1;
  this.Text = numFrom.ToString() + " to " + numTo.ToString();
}

If IntegralHeight=False then you might have to play with the range number to determine whether or not to include partial rows or not.

If using DrawMode=OwnerDrawVariable, then you need to loop through the visible rows with the MeasureItem event.

LarsTech
  • 80,625
  • 14
  • 153
  • 225
0

This is a Draw, you can do this

    private int min = 1000;
    private int max = 0;
    private void comboBox3_DrawItem(object sender, DrawItemEventArgs e)
    {
        if (min >= e.Index) min = e.Index+1;
        if (max <= e.Index) max = e.Index+1;

        float size = 10;
        System.Drawing.Font myFont;
        FontFamily family = FontFamily.GenericSansSerif; 

        System.Drawing.Color animalColor = System.Drawing.Color.Black;
        e.DrawBackground();
        Rectangle rectangle = new Rectangle(2, e.Bounds.Top + 2,
                e.Bounds.Height, e.Bounds.Height - 4);
        e.Graphics.FillRectangle(new SolidBrush(animalColor), rectangle);
        myFont = new Font(family, size, FontStyle.Bold);
        e.Graphics.DrawString(comboBox3.Items[e.Index].ToString(), myFont, System.Drawing.Brushes.Black, new RectangleF(e.Bounds.X + rectangle.Width, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));

        e.DrawFocusRectangle();

        label1.Text = String.Format("Values between {0} and {1}",min,max);
    }

you have to find the right event to reset min and max values and the right values to redraw the combobox.

This code is not a solution, it's only an idea of how you can implement your requirement.

best regards.

manuellt
  • 669
  • 2
  • 7
  • 19