【问题标题】:C# ComboBox paint is freezingC# ComboBox 绘制冻结
【发布时间】:2019-02-10 20:58:47
【问题描述】:

我编写了相当大的(4700 行)Windows 窗体应用程序,用于协调制造工厂的三个部门。我在整个应用程序中有许多组合框,并且都可以正常工作,但是我有一个组合框,它的油漆在加载时可以正常工作,但是一旦您更改选项卡并回来,组合框就会被冻结。请注意:对象的顺序是 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() 均未成功。
* 组合框的 Draw Mode 属性设置为 Normal
* winforms tabcontrol
* suspend paint
* force paint event

我被难住了。有关如何解决此问题的任何想法?

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

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();
        }

【问题讨论】:

  • UI 切换到此选项卡时是否发生了事件?即组合框是否在初始化后重新填充?我们在这个控件中讨论了多少个 ComboBoxItem?
  • 感谢 LordWilmore,Aleksa Ristic 能够解决我的问题。

标签: c# winforms combobox refresh paint


【解决方案1】:

解决这个问题非常简单。只需在将datasource 分配给组合框之前输入ValueDisplay 成员代码即可。

所以而不是:

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 行时,它会“冻结” - 完成时间太长。

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

重要提示:正如我在任何地方都测试和使用过的作品一样,期待checkedListBoxListBox。由于某种原因,它不允许我在分配数据源之前分配Display and Value 成员。

【讨论】:

  • 非常感谢!我所做的唯一更改是将值和显示成员添加到我已经拥有的 if 语句中。
    if (cbFGPN.DataSource == null) { cbFGPN.DataSource = dt; cbFGPN.ValueMember = "材料"; cbFGPN.DisplayMember = "材料"; } else { cbFGPN.ValueMember = "材料"; cbFGPN.DisplayMember = "材料"; cbFGPN.DataSource = dt; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多