【发布时间】:2017-10-28 09:05:00
【问题描述】:
我遇到了非常奇怪的 WinForms 行为,这似乎是一个框架错误。
情况:
在一个空白表格上,将 2 个ListViews 并排放置。禁用HideSelection 以在控件没有焦点时使选择可见。 View 属性(细节,大图标)似乎无关紧要,但我发现细节更容易点击(在这种情况下,添加一列)。
MultiSelect 是否启用也无关紧要。
(不涉及button1)
在表单构造函数中,将一些项目放入列表中:
this.listView1.Items.Add("item1-1");
this.listView1.Items.Add("item1-2");
this.listView1.Items.Add("item1-3");
this.listView2.Items.Add("item2-1");
this.listView2.Items.Add("item2-2");
现在,当用户在listView1 中选择某些内容时,我们希望在listView2 中选择具有相同列表索引的项目。例如。用户在左侧列表视图中选择item1-1,我们要在右侧列表视图中选择item2-1,依此类推。
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
// (*1)
this.listView2.SelectedIndices.Clear();
if (this.listView1.SelectedIndices.Count != 0 && this.listView1.SelectedIndices[0] < this.listView2.Items.Count)
{
// (*1) can also be put here; it makes no difference with regards to the bug (it makes a functional difference though)
this.listView2.SelectedIndices.Add(this.listView1.SelectedIndices[0]);
}
}
错误有时会出现在以下场景中(如果我非常快速地执行这些步骤(例如,总共不到一秒),我只能重现):
- 单击左侧列表中的第 1 项(从 1 开始计数)
- 自动选中右侧列表中的第 1 项
- 单击右侧列表中的第 1 项
- 单击左侧列表中的第 2 项
- 右侧列表中的第 2 项自动被选中
- 单击右侧列表中的第 2 项
- 单击左侧列表中的第 1 项
- 自动选中右侧列表中的第 1 项
- 等一下(大约 300 毫秒)
- 右侧列表中的第 2 项被自动选中(不正确!)
更笼统地说(这是我的猜想):
- 点击左侧列表中的项目
- 单击右侧列表中的项目刚刚被自动选中
- 快速在左侧列表中选择一个不同的项
- 会在正确的列表中自动选择正确的项目片刻
- 选择会在短暂延迟后跳回上一项
我还可以使用此事件处理程序观察右侧列表中的无效选择更改,但我无法从断点中获得任何用途 - 我似乎没有任何可疑之处。在错误的情况下,调用堆栈只包含框架内部方法(除了最顶层的框架,当然是事件处理程序),所以虚假的选择变化来自框架本身。
private void listView2_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.listView1.SelectedIndices.Count == 0 || this.listView2.SelectedIndices.Count == 0)
{
return;
}
if (this.listView2.SelectedIndices[0] != this.listView1.SelectedIndices[0])
{
// Unless the user MANUALLY selects a DIFFERENT item in the right list view, this should never happen, but it does!
int j = 5; // BREAKPOINT HERE
}
}
这个错误并不总是发生,而且似乎对时间很敏感,但经过一些“练习”后,我现在可以在大约 50% 的时间内重现它。
我的猜测是那里有一些非常愚蠢的故障保护机制。当用户单击一个项目时,WinForms 只是决定稍后检查该项目是否真的被选中,如果它没有被选中,它会再次选择它(即使在此期间以编程方式更改了选择)。但仅此而已,因为除非您在选择自动更改后立即明确单击自动选择的项目,否则不会发生该错误。
谁能重现这个,我该如何解决这个问题?
这发生在我的 Win 10 x64 上,带有 .NET 框架 4.5.2 和 4.7
【问题讨论】:
-
这和Winforms没有太大关系,ListView是操作系统提供的,已经经历了20年的appcompat hack。该选择是不可靠的,您已经通过测试 SelectedIndices.Count == 0 发现了这一点。您同样希望避免 SelectedIndices.Clear()。
-
@HansPassant 这听起来有点像你在建议我应该避免使用
ListView开始(或至少避免以编程方式选择事物)并以不同的方式设计 GUI。事实上,这就是我目前正在尝试做的事情。但是我还是觉得这个问题很奇怪,因为除非它特别与我的机器有关,否则这意味着每个从代码中选择项目的人迟早都会遇到这个问题?