首页 > 解决方案 > C# ComboBox 绘制冻结

问题描述

我编写了相当大的(4700 行)Windows Forms 应用程序来协调制造工厂的三个部门。我在整个应用程序中有许多组合框,并且都可以正常工作,但是我有一个组合框,它的油漆在加载时可以正常工作,但是一旦您更改选项卡并返回,组合框就会冻结。请注意:这是对象 Form1 > TableLayoutPanel > TabControl > TabPage > TableLayoutPanel > ComboBox 的顺序。

负载: 在此处输入图像描述

更改选项卡后(它涂有我刚刚单击的选项卡的任何背景): 在此处输入图像描述

解决此问题的唯一方法是关闭应用程序并重新打开。只要我留在选项卡上,控件就会一直完美运行。

这是我为组合框加载数据的方式:

private void LoadFGPN()
    {
        SqlConnection con = new SqlConnection(Properties.Resources.Tef7_Conn);

        SqlDataAdapter da;
        DataTable dt = new DataTable();
        StringBuilder sql = new StringBuilder();
        sql.Append("SELECT DISTINCT(material) FROM [TEF7].[CM].[ALLPartNumbers] WHERE material LIKE '_____7______-6RP' OR material LIKE '_____4______-6RP' OR material LIKE '_________8__-6ML' OR material LIKE '_________[0-7,9]__-6ML'");

        da = new SqlDataAdapter(sql.ToString(), con);
        da.Fill(dt);

        if (cbFGPN.DataSource == null)
        {
            cbFGPN.DataSource = dt;
        }
        else
        {
            cbFGPN.DataSource = null;
            cbFGPN.DataSource = dt;
        }
        cbFGPN.ValueMember = "material";
        cbFGPN.DisplayMember = "material";
    } //loads finished good combo box on kanban

我试过的:
* SelectionChangeCommitted 事件并单独添加 .Refresh() 和 .Invalidate() / .Update() 没有成功。
* 组合框的绘制模式属性设置为正常
* winforms tabcontrol
*暂停绘制
*强制绘制事件

我难住了。有想法该怎么解决这个吗?

编辑:只是为了荒谬,我尝试了以下但没有成功。控件保持隐藏状态。

if (tcMain.SelectedIndex == 0)
        {
            cbFGPN.Hide();
            LoadPreOrderGridview("eKanban", null, null, null, null, null); //loads preorder gridview
            LoadFGPN();
            LoadRawPN();
            cbFGPN.Show();
            tlpMain.Refresh();
            tcMain.Refresh();
            tpKanban.Refresh();
            tlpKanban.Refresh();
            pnKanban.Refresh();
            cbFGPN.Refresh();
        }

标签: c#winformscomboboxrefreshpaint

解决方案


解决这个问题非常简单。只需在分配给组合框之前输入Value和成员代码。Displaydatasource

所以而不是:

if (cbFGPN.DataSource == null)
{
    cbFGPN.DataSource = dt;
}
else
{
    cbFGPN.DataSource = null;
    cbFGPN.DataSource = dt;
}
cbFGPN.ValueMember = "material";
cbFGPN.DisplayMember = "material";

做:

cbFGPN.ValueMember = "material";
cbFGPN.DisplayMember = "material";

if (cbFGPN.DataSource == null)
{
    cbFGPN.DataSource = dt;
}
else
{
    cbFGPN.DataSource = null;
    cbFGPN.DataSource = dt;
}

为什么会发生?

当您要分配DisplayMemberValueMember已经填充的元素时,它会转到该元素中的每个对象并向其写入要使用的display内容和value成员的内容,并且每次他输入已经存在的对象时,它都会触发很少的事件(例如验证,验证, textChanged、dataSourceChanged 和其他(取决于元素)),当您需要触发 10 个事件 * 4700 行时,它会“冻结” - 完成时间太长。

当您在数据源之前分配数据源然后仅更改一次数据源时,所有对象都会继承Displaymember和成员属性并且不会触发事件,因此它不会冻结。ValueMemberDisplayValue

重要提示:正如我已经测试和使用过的一样,它在任何地方都可以使用checkedListBox,并且ListBox. 出于某种原因,它不允许我Display and Value在分配数据源之前分配成员。


推荐阅读