TreeView 未完全展开并选择项目

问题描述 投票:0回答:1

我正在我的应用程序中使用 TreeView,并且具有以下结构:

-Main
  --Test Category A
    ---A.1
      ----T1
      ----T2
  --Test Category B
    ---B.1
      ----T1
      ----T2

当从查找窗口中选择一个项目(例如,T.1)时,我希望 TreeView 自动展开并选择相应的节点。

预期行为: 如果选择 T.1,TreeView 应如下展开:

-Main
  --Test Category A
    ---A.1
     ----T1 

并突出显示/选择 T.1。

当前行为: 运行代码时,仅展开父节点(-Main),但(测试类别 A)和(A.1)不展开。

如果我事先手动展开和折叠 TreeView,代码将按预期工作,完全展开并选择正确的节点。

这是我的 MainWindow.xaml.cs 中的代码片段:

public void SelectTreeViewItem(TestCaseNode selectedItem)
{
    if (selectedItem == null)
        return;

    TestCasesTree.UpdateLayout();

    var tvi = FindTviFromObjectRecursive(TestCasesTree, selectedItem);

    if (tvi != null)
    {
        tvi.IsSelected = true;
        tvi.BringIntoView(); 
    }
}

public static TreeViewItem FindTviFromObjectRecursive(ItemsControl ic, object o)
{
    if (ic == null)
        return null;

    TreeViewItem result = null;

    foreach (object item in ic.Items)
    {
        TreeViewItem tvi = ic.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

        if (tvi != null)
        {
            tvi.IsExpanded = true;
            tvi.UpdateLayout();

            if (item.Equals(o))
            {
                result = tvi;
            }

            TreeViewItem childResult = FindTviFromObjectRecursive(tvi, o);
            if (childResult != null)
            {
                result = childResult;
            }
        }
    }

    return result;
}


为什么 TreeView 第一次尝试无法完全展开并选择节点?如何修改代码以确保 TreeView 的行为符合预期而不需要手动干预?

任何帮助或指示将不胜感激!谢谢你。

编辑(更新):

我相信问题不在于我以前的代码,而在于我如何处理传递测试用例 ID。我有一个主窗口,用户可以在其中打开名为“搜索”的用户控件。当“搜索”窗口打开时,它出现在主窗口的顶部。在此“搜索”窗口中,用户选择一个测试用例 ID 并单击“搜索”。

我怀疑问题出在这里:在 UserControl 完全关闭之前,TestCase ID 被转发到 MainWindow,导致 Treeview UI 在第一个元素之外保持不更新。这似乎会影响 FindTviFromObjectRecursive(TestCasesTree, selectedItem) 函数的执行,该函数在仅扩展第一个元素(打开搜索窗口时存在的元素)后返回 Null。

这是我的 UserControl MainWindowViewModel.cs 的相关部分:


public TestCaseNode SelectedTreeViewItem 
{
 ...

 set
 {
  ...
  ((MainWindow))Application.Current.MainWindow).SelectTreeViewItem(value);

 }

}

public void HighlightAndSelectTestCase(TestCaseNode testCase)
{
 ... 

 SelectedTreeViewItem = testCase;

}

这是我的 UserControl SearchwindowVM.cs 的相关部分:

public SearchWindowVM(MainWindowViewModel mainWindowViewModel)
{
    // Code initialization...
    NotifyMainWindow = (testCase) =>
    {
        _mainWindowViewModel.HighlightAndSelectTestCase(testCase);
    };
}

public void CloseClick()
{
    if (SelectedTestCase != null)
    {
        DialogHost.CloseDialogCommand.Execute(null, null);
        NotifyMainWindow?.Invoke(SelectedTestCase);
    }
}

不幸的是,我对此有点迷失。

c# wpf mvvm listbox treeview
1个回答
0
投票

您可以考虑的一件事是采用基于路径的方法来定位树节点,例如

Main\Test Category B\B.1\T1

private TreeViewItem? FindItemByPath(TreeView treeView, string path)
{
    string[] nodes = path.Split(Path.DirectorySeparatorChar);
    ItemsControl currentLevel = treeView;
    foreach (string header in nodes)
    {
        bool found = false;
        foreach (var item in currentLevel.Items)
        {
            if (item is TreeViewItem treeViewItem && treeViewItem.Header.ToString() == header)
            {
                currentLevel = treeViewItem;
                found = true;
                break;
            }
        }
        if (!found)
        {
            return null;
        }
    }
    return currentLevel as TreeViewItem;
}

无论您如何找到该项目,接下来您想要的是迭代并扩展其所有父项。

private void SelectItem(TreeViewItem item)
{
    var parent = VisualTreeHelper.GetParent(item);
    while (parent is TreeViewItem parentItem)
    {
        parentItem.IsExpanded = true;
        parent = VisualTreeHelper.GetParent(parentItem);
    }
    item.IsSelected = true;
    item.BringIntoView();
}

selection

© www.soinside.com 2019 - 2024. All rights reserved.