我正在尝试创建一个绑定到列表的listBox,当它检查或对列表的每个元素执行某个进程时,它将更改列表框控件上该项的颜色。第一次加载列表框时,它会显示列表中的所有元素,并通过我的listbox_Drawitem事件处理程序接收DrawItemEventArgs事件。但是当我想刷新列表框以重新绘制具有更新状态或颜色的项目时,它永远不会通过listbox_DrawItem事件处理程序。
我尝试单独使用刷新方法但没有成功。我已经尝试将list.Datasource设置为null,然后是list.refresh,它会清除列表框中的每个内容,然后再次将数据源设置到我的列表并刷新但没有任何反应。
我正在使用两个线程,当我从我的UI表单以外的另一个线程编辑我的控件时,我通过委托来完成它以避免交叉线程错误。到目前为止它一直在工作,除了DrawItem处理程序应该通过我的委托中的safeRefreshAllMethod内部的刷新重新绘制我的控件来触发。
这是我的UI表单中的代码:
public partial class Form1 : Form
{
public delegate void SafeRefresh();
public SafeRefresh myDelegate;
private Form1 currentForm;
Thread scriptThread;
public Form1()
{
InitializeComponent();
currentForm = this;
myDelegate = new SafeRefresh(SafeRefreshAllMethod);
}
private async void button_script_Click(object sender, EventArgs e)
{
scriptThread = new Thread( () => SomeClass.RunScript(currentForm));
scriptThread.Start();
}
public void SafeRefreshAllMethod()
{
listBox.DataSource = null;
listBox.Refresh();
listBox.DataSource = Global.ListAllItems;
listBox.Refresh();
}
public void listBox_DrawItem(object sender, DrawItemEventArgs e)
{
Brush myBrush;
if (Global.ListItemsDisconnected.Contains(Global.ListAllItems[e.Index] ))
{
myBrush = Brushes.Gray;
}
else if (Global.ListItemsConnected.Contains(Global.ListAllItems[e.Index]))
{
myBrush = Brushes.Green;
}
else
{
myBrush = Brushes.Black;
}
e.DrawBackground();
e.Graphics.DrawString(listBox.Items[e.Index].ToString(), listBox.Font, myBrush, e.Bounds);
}
}
这是由表单中的新线程执行的代码,它调用委托来刷新列表框控件:
class SomeClass {
public static void RunScript(Form1 theForm)
{
theForm.Invoke(theForm.myDelegate);
foreach (string item in Global.ListAllItems)
{
//some code that works with the items on list
//if disconnected : adds to Global.ListItemsDisconnected
//if connected: adds it to Global.ListItemsConnected
theForm.Invoke(theForm.myDelegate);
}
}
}
我想知道是否有人知道为什么listBox_DrawItem,当线程第一次调用控件时触发,绘制列表中的所有项目。但是当我尝试刷新并使用不同颜色重绘列表时,处理程序永远不会被调用。
查看Designer并尝试将DrawMode属性更改为OwnerDrawFixed。