C# Winforms列表框显示项目两次
我在Winforms应用程序中遇到了一个C# Winforms列表框显示项目两次,c#,winforms,listbox,C#,Winforms,Listbox,我在Winforms应用程序中遇到了一个列表框的问题,它以意外的顺序添加了两次条目 到目前为止的故障排除步骤 listStepHistory未在代码中的任何其他位置引用(当然,Designer.cs文件除外)。它没有绑定到数据源 我已双重检查了Job.Progress.StepHistory属性,它两次未包含相同的消息。每一段代码都只提到一次,这是应该的 起初,我认为这是一个多个更新同时发生的问题。但是,我已经将Task.Delay(TimeSpan.frommissions(500))的值
列表框的问题,它以意外的顺序添加了两次条目
到目前为止的故障排除步骤
listStepHistory
未在代码中的任何其他位置引用(当然,Designer.cs文件除外)。它没有绑定到数据源
- 我已双重检查了
Job.Progress.StepHistory
属性,它两次未包含相同的消息。每一段代码都只提到一次,这是应该的
- 起初,我认为这是一个多个更新同时发生的问题。但是,我已经将
Task.Delay(TimeSpan.frommissions(500))
的值减少或增加到极值(1,10100100010000),并且从未见过两个以上的条目,也从未见过两个以下的条目。这似乎排除了并发UI更新是问题的原因
值得注意
如果您回顾屏幕截图,您将看到Winforms选择了代码最高的行(数字),这在导入作业的整个过程中是一致的,最高的数字始终是所选择的。这是有道理的,因为我在处理代码之前对代码进行了排序,所以它们应该按数字顺序进行处理。
如果查看所选项目之后的项目,您将看到这是一个较小的代码。这一行(11004)实际上与列表框顶部的第一行相同。类似地,所选行(73109)与列表框的底部相同
换句话说,复制如下所示(并且粗体被选中):
A B C DEA 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
属性中
我由此得出结论,列表框呈现的内容与其项
属性中包含的内容不同
有人能解释这种行为吗
附录
根据要求,作业
和作业进度
接口/类定义:
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>();
}
公共接口IProgressTrackable
{
ImportProgress进度{get;}
void Start();
bool Cancel();
}
公共类导入程序
{
//为简洁而编辑
公共列表历史记录{get;set;}=new List();
}
只需添加数组,而不是使用new ListBox.ObjectCollection
listStepHistory.Items.AddRange(Job.Progress.StepHistory.ToArray());
不使用新的ListBox.ObjectCollection,只需添加数组即可
listStepHistory.Items.AddRange(Job.Progress.StepHistory.ToArray());
在我看来,您正在循环中多次调用StartProgressTracking()
。这个环是干什么用的?是不是每半秒投票一次?我会尝试通过将500毫秒更改为10000秒来排除重入,只是为了看一看。@EdPlunkett:StartProgressTracking()
不是从循环内部调用的。此外,尽管问题中的示例中省略了“开始”按钮,但在单击后,“开始”按钮实际上会自动禁用,不能启动两次,也可以通过断点确认)我在第三个故障排除步骤中特别提到了修改延迟时间。重复条目(总是完全是双条目)似乎排除了并发问题(我希望在极短的延迟内有超过2个条目,并且问题会以足够大的延迟自行修复,但两者都不是),这就是“错误”的原因项目被选中是指您两次添加相同的实际对象实例列表。当您告诉它选择一个给定对象时,它会在Items
中找到与该对象相等的第一个对象并选择它。最后一个对象在其中有两次,但第一次出现是它选择的。对不起,我的意思是从循环中调用updatejobiformation()
。@EdPlunkett:注意,我设置了SelectedIndex
,而不是SelectedItem
SelectedIndex
不检查项目是否相等。另外,我第二次在哪里添加列表?在我看来,您在循环中多次调用StartProgressTracking()
。这个环是干什么用的?是不是每半秒投票一次?我会尝试通过将500毫秒更改为10000秒来排除重入,只是为了看一看。@EdPlunkett:StartProgressTracking()
不是从循环内部调用的。此外,尽管问题中的示例中省略了“开始”按钮,但在单击后,“开始”按钮实际上会自动禁用,不能启动两次,也可以通过断点确认)我在第三个故障排除步骤中特别提到了修改延迟时间。重复条目(总是完全是双条目)似乎排除了并发问题(我希望在极短的延迟内有超过2个条目,并且问题会以足够大的延迟自行修复,但两者都不是),这就是“错误”的原因项目被选中是指您两次添加相同的实际对象实例列表。当您告诉它选择一个给定对象时,它会在Items
中找到与该对象相等的第一个对象并选择它。最后一个对象在其中有两次,但第一次出现是它选择的。对不起,我的意思是从循环中调用updatejobiformation()
。@EdPlunkett:注意,我设置了SelectedIndex
,而不是SelectedItem
SelectedIndex
不检查项目是否相等。还有,我第二次在哪里添加列表?很好的发现!我