【问题标题】:foreach loop seems to slowforeach 循环似乎变慢了
【发布时间】:2016-07-12 12:57:22
【问题描述】:

我目前正在尝试将一些自定义控件添加到 winforms 中的面板。 每个控件都将停靠并构建类似“列表”的东西。 现在我正在尝试实现一个功能来选择/取消选择每个控件。 它工作正常,我的问题是它有时似乎很慢。 目前它在面板中大约有 50 个自定义控件。

modtable.Click += (s, e) =>
{
    foreach (Control m in pnl_ucMods.Controls)
    {
        if(m is ModTableEntry)
        {
            if(m != modtable)
            {
                ((ModTableEntry)m).BackColor = SystemColors.Control;
            }
            else if (m == modtable && m.BackColor == SystemColors.Control)
                m.BackColor = SystemColors.ActiveCaption;
            else
                m.BackColor = SystemColors.Control;
        }
    }
};

每当我点击其中一个控件时,它都会改变背景颜色,第二次点击它会改变它,但只有在我再次点击之前等待一秒钟,它才会起作用。如果我点击快速,没有任何反应,我必须再次点击。 我知道 winforms 的设计不是为了拥有大量控件,而且我知道 foreach 需要一些时间来循环遍历所有控件,但也许这里有人对如何改进代码有一个小想法,也许可以解决这个问题。

tl;博士

单击面板中的自定义控件之一将更改其背景颜色。 (已选择)

所有其他控件也会改变背景颜色(取消选择)

如果点击的控件已经被选中,它将取消选择。

编辑: 一个小例子来测试这个问题。 只需新建一个项目,添加代码并调用即可。

private void addPanels()
{
    Panel newPanel = new Panel();
    newPanel.AutoScroll = true;
    newPanel.Dock = DockStyle.Fill;
    this.Controls.Add(newPanel);

    for (int i = 0; i < 50; i++)
    {
        Panel childPanel = new Panel();
        childPanel.Size = new Size(100, 30);
        childPanel.Dock = DockStyle.Top;

        childPanel.Click += (s, e) =>
        {
            foreach (Control p in newPanel.Controls)
            {
                if (p is Panel)
                {
                    if (p != childPanel)
                        ((Panel)p).BackColor = SystemColors.Control;
                    else if (p == childPanel && p.BackColor == SystemColors.Control)
                        p.BackColor = SystemColors.ActiveCaption;
                    else
                        p.BackColor = SystemColors.Control;
                }
            }
        };
        newPanel.Controls.Add(childPanel);
    }
}

【问题讨论】:

  • @JohnCarpenter 基本上是的。应该可以单击每个控件。单击它会更改该面板中的所有其他控件以及被单击的控件。这不是正确的方法吗?有没有更好的办法?
  • 您在哪里添加Click 事件处理程序?为什么不让它成为一个函数而不是一个 lambda?我想知道你是不是无意中多次添加了事件处理程序。
  • 不到 1 毫秒。你的期望是什么?
  • @Backslash 如果你点击太快,那就是 DoubleClick。
  • 代码中的另一个问题是您在事件处理程序委托中使用childPanel。而是使用var sender = (Control)s;。这可能会导致一些问题,因为您在每个循环过程中都创建了新的子面板。

标签: c# winforms performance foreach


【解决方案1】:

使用MouseDown 事件而不是Click 事件。

当您点击两次的速度太快时,这将是一个DoubleClick 事件,并且不会引发其他Click 事件。

在您的允许下,雷扎。

【讨论】:

  • 我不知道为什么,但很简单,这解决了问题。
  • 我的母语不是英语,所以很难描述。 Click 事件由两个事件组成:MouseDownMouseUp。因此,它可能不会经常发生。
  • 也许将这个事实添加到答案中,让未来的读者更清楚:当您点击两次太快时,这将是一个 DoubleClick 事件,并且不会引发其他 Click 事件。
  • 如果有人用正确的语言描述了这种行为,那就太好了。我会投赞成票的。
  • 我相信这个问题不需要另一个答案,将我在 cmets 中提到的那部分添加到您的答案中就足够了。然后你会得到我的投票:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多