我在WinForms中有一个显示一些数据的ListBox,当你点击一个项目时,它会展开并显示更多数据。这是代码:
private void historyList_SelectedIndexChanged(object sender, EventArgs e)
{
historyList.Refresh();
}
private void historyList_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
FeedHistoryItem item = (sender as ListBox).Items[e.Index] as FeedHistoryItem;
if (e.Index == historyList.SelectedIndex)
{
e.Graphics.DrawString(item.ExpandedText,
e.Font, Brushes.Black, e.Bounds);
}
else
{
e.Graphics.DrawString(item.CollapsedText,
e.Font, Brushes.Black, e.Bounds);
}
e.DrawFocusRectangle();
}
private void historyList_MeasureItem(object sender, MeasureItemEventArgs e)
{
FeedHistoryItem item = (sender as ListBox).Items[e.Index] as FeedHistoryItem;
string itemText = e.Index == historyList.SelectedIndex ? item.ExpandedText : item.CollapsedText;
int size = 15 * (itemText.Count(s => s == '\r') + 1);
e.ItemHeight = size;
}
事件按预期调用。当您单击某个项目时,它会调用Refresh(),然后测量,然后绘制。文字扩大了。但是,尺寸不会改变。
我已经验证了第一次绘制项目时,它会在我放入ItemHeight时受到尊重,但是在调整大小时,它不会 - 如果我在DrawItem方法中设置断点,即使刚刚调用了MeasureItem, e.Bounds中的高度不会更新。是的 - 我确实有historyList.DrawMode = DrawMode.OwnerDrawVariable;集。
有什么想法吗?
答案 0 :(得分:2)
尝试继承ListBox控件并在OnSelectedIndexChanged方法上调用RecreateHandle。
public class ListEx : ListBox {
protected override void OnSelectedIndexChanged(EventArgs e) {
base.OnSelectedIndexChanged(e);
this.RecreateHandle();
}
}
不幸的是,它可能会闪烁,但我认为这是让ListBox再次调用MeasureItem事件的唯一方法。另一种方法是暂停绘图,然后从列表中删除该项目并再次将其重新放入。在WinForms中没有干净的方法。
答案 1 :(得分:0)
我需要类似的内容:调整ListBox
的大小时,我也需要调整项目的大小以适应新的宽度。
因此,每次调整ListBox的大小时,我都会调用以下方法,该方法将调整每个项目的大小! (当您有太多物品时要小心)
private static void ForceMeasureItems(ListBox listBox, Action<object, MeasureItemEventArgs> onMeasureEvent)
{
for (int i = 0; i < listBox.Items.Count; i++)
{
MeasureItemEventArgs eArgs = new MeasureItemEventArgs(listBox.CreateGraphics(), i);
onMeasureEvent(listBox, eArgs);
SendMessage(listBox.Handle, LB_SETITEMHEIGHT, i, eArgs.ItemHeight);
}
listBox.Refresh();
}
用法:
private void OnMyMeasureItem(object sender, MeasureItemEventArgs e)
{
// measure logic goes here
int myCustomHeightValue = 22;
e.ItemHeight = myCustomHeightValue;
}
ListBox listBox = new ListBox();
listBox.MeasureItem += OnMyMeasureItem;
listBox.Resize += (sender, args) => ForceMeasureItems(listBox, OnMyMeasureItem);