copying the listbox behaviour in "Add/Remove Programs"

D

Dan Bass

[Problem]
I'm looking to develop a listbox with in-place editing where as each item is
selected, it grows to fit in all the text boxes. When the item is
deselected, it shrinks back to its original size. The editing bit is not a
problem, but I can't get the selected item to resize, as the listbox does
for the "Add/Remove programs".

[Approach]
The initial thought I had was to have a handler for the MeasureItem event,
then have the condition of whether the current index was selected or not,
basing the height on this.
The SelectionChange event would then call a refresh on the list box, which
in turn would cause the MeasureItem event to fire, finally leaving the
DrawItem event handler to draw the items as required.
Is this thinking logical and workable?

Code:
protected void _listBox_DrawItem(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
if ( e.Index < 0 )
{
selectionPanel.Hide();
return;
}

if ( (e.State & DrawItemState.Selected) ==
DrawItemState.Selected )
{
// The e.Bounds rect appears to remain unchange from the
initial
// MeasureItem event handler settings, and any changes made
// after this seems to be ignored when getting to this
method.

// put the editing panel in the selection spot
selectionPanel.Size = new Size ( e.Bounds.Width,
e.Bounds.Height );
selectionPanel.Location = new Point ( e.Bounds.Location.X+1,
e.Bounds.Location.Y+1 );
selectionPanel.BackColor = SelectedBackgroundColor;
selectionPanel.Show();

}
else
{
// draw unselected items
DrawInterfaceItem(
((InboundInterface)(_itemArray[e.Index])).name,
((InboundInterface)(_itemArray[e.Index])).type,
((InboundInterface)(_itemArray[e.Index])).messageType,
e );
}
}

private void _listBox_MeasureItem(object sender,
System.Windows.Forms.MeasureItemEventArgs e)
{
// this does indeed fire on each selection change and
// can trace the e.ItemHeight being set for selected
// items as expected.
if ( _listBox.SelectedIndex == e.Index )
{
// set the item height to that of the selection panel
e.ItemHeight = selectionPanel.Height;
}
else
{
// items not selected use a default item height
e.ItemHeight = _defaultItemHeight;
}
}

private void _listBox_SelectedIndexChanged(object sender,
System.EventArgs e)
{
// cause a redraw, and MeasureItem to fire
_listBox.Refresh();
}

Thanks for your time.
Dan.
 
D

Dan Bass

I managed to get this to work! Think I feel a article coming on...

It's done in short, on the following principle:
- When you reinsert an item, it fires the MeasureItem event for that item.
- You need to reinsert the newly selected index, as well as the last
selectedIndex...

Hope this helps someone else.

Code:
bool _updatingSelectedIndex = false;
bool _processingSelectionChange = false;
int _lastSelectedIndex = -1;

private void _listBox_MeasureItem(object sender,
System.Windows.Forms.MeasureItemEventArgs e)
{
if ( _updatingSelectedIndex )
{
e.ItemHeight = selectionPanel.Height;
}
else
{
e.ItemHeight = _defaultItemHeight;
}
}

private void _listBox_SelectedIndexChanged(object sender,
System.EventArgs e)
{
if ( _listBox.Items.Count <= 0 )
{
return;
}

if ( !_processingSelectionChange )
{
_processingSelectionChange = true;

// re-evaulate the last selected item height
if ( _lastSelectedIndex >= 0 )
{
int position = _lastSelectedIndex;
Object item = _listBox.Items[position];
_listBox.Items.RemoveAt(position);
_listBox.Items.Insert(position, item);
}

_lastSelectedIndex = _listBox.SelectedIndex;

if ( !_updatingSelectedIndex && _listBox.SelectedIndex >=
)
{
_updatingSelectedIndex = true;

// re-evaulate the selected item height
int position = _listBox.SelectedIndex;
Object item = _listBox.Items[position];
_listBox.Items.RemoveAt(position);
_listBox.Items.Insert(position, item);
_listBox.SelectedIndex = position;

_updatingSelectedIndex = false;

}

_processingSelectionChange = false;

}

}



[QUOTE="Dan Bass"]
[Problem]
I'm looking to develop a listbox with in-place editing where as each item
is selected, it grows to fit in all the text boxes. When the item is
deselected, it shrinks back to its original size. The editing bit is not a
problem, but I can't get the selected item to resize, as the listbox does
for the "Add/Remove programs".

[Approach]
The initial thought I had was to have a handler for the MeasureItem event,
then have the condition of whether the current index was selected or not,
basing the height on this.
The SelectionChange event would then call a refresh on the list box, which
in turn would cause the MeasureItem event to fire, finally leaving the
DrawItem event handler to draw the items as required.
Is this thinking logical and workable?

[Code]
protected void _listBox_DrawItem(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
if ( e.Index < 0 )
{
selectionPanel.Hide();
return;
}

if ( (e.State & DrawItemState.Selected) ==
DrawItemState.Selected )
{
// The e.Bounds rect appears to remain unchange from the
initial
// MeasureItem event handler settings, and any changes made
// after this seems to be ignored when getting to this
method.

// put the editing panel in the selection spot
selectionPanel.Size = new Size ( e.Bounds.Width,
e.Bounds.Height );
selectionPanel.Location = new Point (
e.Bounds.Location.X+1, e.Bounds.Location.Y+1 );
selectionPanel.BackColor = SelectedBackgroundColor;
selectionPanel.Show();

}
else
{
// draw unselected items
DrawInterfaceItem(
((InboundInterface)(_itemArray[e.Index])).name,
((InboundInterface)(_itemArray[e.Index])).type,
((InboundInterface)(_itemArray[e.Index])).messageType,
e );
}
}

private void _listBox_MeasureItem(object sender,
System.Windows.Forms.MeasureItemEventArgs e)
{
// this does indeed fire on each selection change and
// can trace the e.ItemHeight being set for selected
// items as expected.
if ( _listBox.SelectedIndex == e.Index )
{
// set the item height to that of the selection panel
e.ItemHeight = selectionPanel.Height;
}
else
{
// items not selected use a default item height
e.ItemHeight = _defaultItemHeight;
}
}

private void _listBox_SelectedIndexChanged(object sender,
System.EventArgs e)
{
// cause a redraw, and MeasureItem to fire
_listBox.Refresh();
}

Thanks for your time.
Dan.
[/QUOTE]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top