ListBox的Refresh方法不会触发DrawItem属性的事件处理程序

问题描述 投票:0回答:1

我正在尝试创建一个绑定到列表的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,当线程第一次调用控件时触发,绘制列表中的所有项目。但是当我尝试刷新并使用不同颜色重绘列表时,处理程序永远不会被调用。

c# forms delegates thread-safety eventhandler
1个回答
0
投票

查看Designer并尝试将DrawMode属性更改为OwnerDrawFixed。

ListBox DrawMode Example

© www.soinside.com 2019 - 2024. All rights reserved.