【发布时间】:2012-01-04 21:38:07
【问题描述】:
在 WPF 中,我有一个 TreeView 控件,可以通过用户直接在树视图中选择项目或单击屏幕控件来选择特定项目。树形视图显示的是用户定义的表单(基本上是表单设计器应用程序)上显示的元素列表。
这是我的问题。当用户单击屏幕控件时,它会调用一个方法,该方法返回代表该元素的 TreeViewItem。然后,它将此元素的 IsSelected 属性设置为 true。它正确更改了 TreeView 中的可视指示器,并在 TreeView 中引发了 SelectedItemChanged 事件。这一切都很好。
但是,TreeView 似乎在幕后的某个地方仍然认为前一个项目已被选中。这就是我得出这个结论的原因。如果我通过在 TreeView 中单击它来选择 ElementA,它是否被正确选择。如果我然后通过单击屏幕控件并以编程方式设置 ElementB TreeViewItem 的 IsSelected 属性来选择 ElementB,则它似乎已正确选择它。现在,如果我通过在 TreeView 中单击它再次选择 ElementA,它什么也不做。未引发 SelectedItemChanged 事件,并且指示所选项目的反向选择框保留在 ElementB 上。如果我单击 TreeView 中的 ElementB,它也不会引发 SelectedItemChanged 事件,但是它似乎不会更新内部标志,因为如果我然后单击 TreeView 上的 ElementA,它会正确处理它并引发事件。
我发现的唯一解决方法是在 SelectedItemChanged 事件处理程序中为现在选择的 TreeViewItem 调用 Focus 方法。如果这样做,当我选择屏幕控件并以编程方式更改选定的 TreeViewItem 时,我会得到预期的行为。
这不是一个可接受的解决方案,因为它会导致焦点更改闪烁。当我在表单窗口中选择项目时,焦点转到 TreeView 控件,然后又回到表单,导致闪烁和轻微延迟。
任何人都有自己的想法。
更新
这里有一些代码。这是我的资源管理器窗口的方法,它是相关 TreeView 的管理器。
public bool SelectItemByName(String controlName)
{
bool fReturn = false;
TreeViewItem tviToSelect = FindItemByName(_tviMaster, controlName);
if (tviToSelect != null && _tviSelectedItem != tviToSelect)
{
tviToSelect.IsSelected = true;
// Make sure the selected item is visible in the TreeView by expanding all of the parent nodes
ExpandAllParents(tviToSelect);
tviToSelect.BringIntoView();
fReturn = true;
}
return fReturn;
}
每个元素都有一个唯一标识符,我将其用作界面不同区域之间的交叉引用。当您单击屏幕控件时,它会使用其标识符在 TreeView 中查找相应的 TreeViewItem。然后这段代码将其设置为选中。
然后在我的 SelectedItemChanged 事件处理程序中,我必须包含以下行。
_tviSelectedItem.Focus();
这解决了我最初的问题,但引入了不需要的屏幕闪烁。
回顾一下,我直接在 TreeView 中选择 ElementA,然后在表单设计器中选择一个或多个其他元素,然后调用 SelectItemByName 以编程方式设置所选项目。所有视觉指标都表明这是有效的。在 TreeView 中,突出显示的项目更改为选中的新项目。在通过表单设计器界面选择任意数量的元素后,如果您通过直接在 TreeView 中单击它来选择 ElementA,它什么也不做。它不会突出显示,也不会触发 SelectedItemChanged 事件。如果您检查 TreeView 的 SelectedItem 和 SelectedValue 属性,它们都正确地对应于以编程方式选择的项目。但是,某处的控件似乎认为 ElementA 仍处于选中状态,并且无法识别选择正在更改。
我不敢相信其他人没有遇到过这种情况。这似乎是 WPF 中 TreeView 控件中的一个重大缺陷。不确定 WinForms 是否有同样的问题。
【问题讨论】: