TableLayoutPanel更新滞后

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

我有一个WinForms应用程序,它正在从BackgroundWorker更新一个TableLayoutPanel。根据设备输入是开(1)还是关(0),颜色和一些文本会相应地改变。

try
{
    //Define a new TLP to hold the search tablelayoutpanel. 
    //search for the iterated card number.
    //get the status label using GetControl from Position.
    TableLayoutPanel TLP = new TableLayoutPanel();
    string IO_Card_Name = "ED527_" + i.ToString();
    TLP = TLP_IO_Info.Controls.Find(IO_Card_Name, true).FirstOrDefault() as TableLayoutPanel;
    try { lbl = TLP.GetControlFromPosition(4, 0) as Label; } catch { lbl = null; };
    //if card is found (because input is active, colour the TLP (card) according to its state.
    if (TLP != null && lbl != null && INPUTS[i - 1] == 1)
    {

        TLP.BackColor = Color.Green;

        foreach (Label l in TLP.Controls)
        {
            l.BackColor = Color.Green;
        }
        lbl.Invoke((MethodInvoker)delegate { lbl.Text = "ON"; });
    }
    else if (TLP != null && lbl != null && INPUTS[i - 1] == 0)
    {
        TLP.BackColor = Color.White;
        foreach (Label l in TLP.Controls)
        {
            l.BackColor = Color.White;
        }
        lbl.Invoke((MethodInvoker)delegate { lbl.Text = "OFF"; });
    }
}
catch (Exception exception)
{
    MessageBox.Show(exception.Message);
};

TLP 在其中容纳了5个标签。行更新时显示出一些明显的滞后。我是否有办法可以进行类似于 SuspendLayout() ResumeLayout 在UI主线上?

****编辑以显示前后的情况--IOLabel列在状态列之前稍微更新。

Table Layout Panel

c# backgroundworker tablelayoutpanel
1个回答
2
投票

听起来你有一个嵌套的设计。每行是5个标签由不同的TableLayoutPanel和the TLP_IO_Info 是一个TableLayoutPanel托管其他TableLayoutPanel。在 DoWork 的事件中,您有一个 for..loop 改变 Backcolor 的内部控制,根据当前的 状况 的设备上读取的。INPUT int数组。请指正。

我想建议这样。

foreach (var tlp in TLP_IO_Info.Controls.OfType<TableLayoutPanel>()
    .Where(x => x.Name.StartsWith("ED527_")))
{
    if (tlp.GetControlFromPosition(4, 0) is Label lbl)
    {
        var state = // get the state of the current device from INPUT array
        var stateColor = state == 1 ? Color.Green : Color.White;
        var stateText = state == 1 ? "ON" : "OFF";
        this.Invoke(new Action(() =>
        {
            tlp.BackColor = stateColor;
            tlp.Controls.OfType<Label>().ToList().ForEach(l => l.BackColor = stateColor);
            lbl.Text = stateText;
        }));                        
    }
}

或者这样来消除多余的代码。

var stateColors = new[] { Color.White, Color.Green };
var stateTexts = new[] { "OFF", "ON" };

foreach (var tlp in TLP_IO_Info.Controls.OfType<TableLayoutPanel>()
    .Where(x => x.Name.StartsWith("ED527_")))
{
    if (tlp.GetControlFromPosition(4, 0) is Label lbl)
    {
        var state = // get the state of the current device from INPUT array
        this.Invoke(new Action(() =>
        {
            tlp.BackColor = stateColors[state];
            tlp.Controls.OfType<Label>().ToList()
            .ForEach(l => l.BackColor = stateColors[state]);
            lbl.Text = stateTexts[state];
        }));
    }
}

请注意,我已经删除了昂贵的... try..catch 块,因为这段代码不会抛出任何异常。

至于 INPUT 数组,我建议你用一个 Dictionary<string, int> 来存储每个设备的当前状态,因为(根据您提供的链接)每个设备都有一个独特的 IOLineNumber 这样你就可以很容易的设置得到每一个的当前状态。

"■▄▄■▓,也许在库中已经有了类似的东西?

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