让TreeView在以编程方式更改时更新其SelectedItem

时间:2011-11-23 15:33:19

标签: wpf treeview

在WPF中,我有一个TreeView控件,可以通过用户直接在树形视图中选择项目或单击屏幕控制来选择特定项目。树视图显示的是在用户定义的表单上显示的元素列表,基本上是表单设计器应用程序。

这是我的问题。当用户单击屏幕控件时,它会调用一个返回表示该元素的TreeViewItem的方法。然后,它将此元素的IsSelected属性设置为true。它正确地更改了TreeView中的可视指示器,并在TreeView中引发了SelectedItemChanged事件。这一切都很好。

然而,看起来在幕后的某个地方,TreeView仍然认为选择了上一个项目。这就是我得出这个结论的原因。如果我通过在TreeView中单击它选择ElementA是否正确选择。如果我然后通过单击屏幕控件选择ElementB并以编程方式设置ElementB TreeViewItem的IsSelected属性,它似乎已正确选择它。现在,如果我通过在TreeView中单击它再次选择ElementA,它什么都不做。未引发SelectedItemChanged事件,并且指示所选项的反向选择框保留在ElementB上。如果我在TreeView中单击ElementB它也不会引发SelectedItemChanged事件,但它似乎不会更新内部标志,因为如果我然后单击TreeView上的ElementA它会正确处理它并引发事件。

我找到的唯一解决方法是在SelectedItemChanged事件处理程序中为现在选择的TreeViewItem调用Focus方法。如果我这样做,当我选择屏幕控制并以编程方式更改所选的TreeViewItem时,我会得到预期的行为。

这不是一个可接受的解决方案,因为它会产生焦点变化闪烁。当我在窗体窗口中选择项目时,焦点将转到TreeView控件,然后返回到窗体,导致闪烁和轻微延迟。

任何人都有任何违约。

更新

这里要求的是一些代码。这是我的Explorer窗口的方法,它是有问题的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是否有同样的问题。

1 个答案:

答案 0 :(得分:0)

每个TreeViewItem都有IsSelected属性,我怀疑旧版本没有设置为false。每当您将新项目设置为true时,请尝试将其设置为false。

var currentItem = treeView.ItemContainerGenerator
    .ContainerFromItem(treeView.SelectedItem) as TreeViewItem;
currentItem.IsSelected = false;

如果不起作用,请尝试在选择项目的同时将焦点设置在新选择的项目上。不要忘记WPF还有两个焦点范围:逻辑焦点和键盘焦点。您可能需要同时设置它们。

treeViewItem.Focus();         // Sets Logical Focus
Keyboard.Focus(treeViewItem); // Sets Keyboard Focus