Winforms列表框两次显示项目

时间:2017-09-06 13:27:00

标签: c# winforms listbox

我在Winforms应用中遇到Listbox的问题,它会以意外的顺序将条目添加两次。

enter image description here

private async void btnStart_Click(object sender, EventArgs e)
{
    Job.Start();

    await StartProgressTracking();
}

public async Task StartProgressTracking()
{    
    while (!Job.Progress.EndTime.HasValue)
    {
        await Task.Run(() => UpdateJobInformation());
        await Task.Delay(TimeSpan.FromMilliseconds(500));
    }
}

private void UpdateJobInformation()
{
    this.UIThread(() => 
    {
        listStepHistory.SelectedIndex = -1;
        listStepHistory.Items.Clear();

        listStepHistory.Items.AddRange(new ListBox.ObjectCollection(listStepHistory, Job.Progress.StepHistory.ToArray()));
        if (listStepHistory.Items.Count > 0)
        {
            //Select the last item (so that it scrolls to the bottom)
            listStepHistory.SelectedIndex = listStepHistory.Items.Count - 1;
        }
    });            
}

// The extension method that I'm using

public static void UIThread(this Control @this, Action code)
{
    if (@this.InvokeRequired)
    {
        @this.BeginInvoke(code);
    }
    else
    {
        code.Invoke();
    }
}
到目前为止

疑难解答步骤

  • listStepHistory未在代码中的任何其他位置引用(当然,除了Designer.cs文件外)。它没有绑定到DataSource。
  • 我已经对Job.Progress.StepHistory属性进行了双重检查,但它不包含两次相同的消息。每个代码都应该提到一次,因为它应该是。
  • 最初,我认为这是同时发生多次更新的问题。但是,我已将Task.Delay(TimeSpan.FromMilliseconds(500))的值减少并增加到极值(1,10,100,1000,10000)并且从未见过超过两个条目,也从不少于两个。这似乎排除了并发UI更新作为问题的原因。

有趣的是

如果你回头看截图,你会看到Winforms选择了具有最高代码的行(数字),这在导入作业的整个过程中是一致的,最高的数字始终是所选择的数字。这是有道理的,因为我在处理代码之前对代码进行了排序,因此应按数字顺序处理它们 如果您在所选项目之后查看该项目,您将看到这是一个较小的代码。该行(11004)实际上与列表框顶部的第一行相同。同样,所选行(73109)与列表框的底部行相同。

换句话说,重复发生如下(粗体 选择):

  

A B C D E A B C D E

这很奇怪,因为我已经指示列表框选择最后一项。请注意我的UpdateJobInformation()方法的最后一步:

if (listStepHistory.Items.Count > 0)
{
    //Select the last item (so that it scrolls to the bottom)
    listStepHistory.SelectedIndex = listStepHistory.Items.Count - 1;
}

即使我错误地将项目添加了两次,我仍然希望列表框仍然选择最后项目(无论它是否重复),但这不是情况下。

在我看来,重复的条目是"幻像条目"。它们被渲染到屏幕上,但它们不存在于listStepHistory.Items属性中。

我从中得出结论,列表框呈现的内容与其Items属性中包含的内容不同。

任何人都可以解释这种行为吗?

附录

根据要求,JobJob.Progress接口/类定义:

public interface IProgressTrackable
{
    ImportProgress Progress { get; }

    void Start();
    bool Cancel();
}

public class ImportProgress
{
    //redacted for brevity

    public List<string> StepHistory { get; set; } = new List<string>();
}

1 个答案:

答案 0 :(得分:2)

而不是使用新的ListBox.ObjectCollection,只需添加数组

listStepHistory.Items.AddRange(Job.Progress.StepHistory.ToArray());