0

我正在尝试向我的 TreeView 添加功能,其中用户可以通过单击按钮让所有节点展开和折叠。Expand 使用 ExpandSubTree 可以很好地工作。无论出于何种原因,都没有 CollapseSubTree 函数。我怎样才能成功完成这项任务?

这是我当前的功能:

private void expand_collapse_children(TreeViewItem tvi, bool expand)
{
    if (tvi.Items.Count > 0)
    {
        foreach (TreeViewItem item in tvi.Items)
        {
            if (expand)
            {
                item.ExpandSubtree();
            }
            else
            {
                expand_collapse_children(item, expand);
                item.IsExpanded = false;
            }
        }
    }
}

注意: isExpanded 比无用的高出半步。当它为真时,我可以将其设置为假,并且它不会折叠超过所选最高级别的任何内容。

谢谢!

4

4 回答 4

1
private static void CollapseRecursive(TreeViewItem item)
{
    // Collapse item if expanded.
    if (item.IsExpanded)
    {
        item.IsExpanded = false;
    }

    // If the item has sub items...
    if (item.Items.Count > 0)
    {
        // ... iterate them...
        foreach (TreeViewItem subItem in item.Items)
        {
            // ... and if they themselves have sub items...
            if (subItem.Items.Count > 0)
            {
                // ... collapse the sub item and its sub items.
                CollapseRecursive(subItem);
            }
        }
    }
}
于 2012-06-07T13:43:56.503 回答
1

我实现了扩展 a 中的所有节点,TreeView如下所示(我有一个类似的功能来折叠所有节点):

foreach (var treeViewItem in MyTreeView.FindVisualDescendants<TreeViewItem>(e => !e.IsExpanded, true)) {
  treeViewItem.IsExpanded = true;
}

哪里FindVisualDescendants有一个方便的扩展方法:

public static IEnumerable<T> FindVisualDescendants<T>(this Visual parent, Func<T, bool> predicate, bool deepSearch) where T : Visual {
  var visualChildren = new List<Visual>();
  var visualChildrenCount = VisualTreeHelper.GetChildrenCount(parent);
  for (var childIndex = 0; childIndex < visualChildrenCount; childIndex++) {
    visualChildren.Add((Visual) VisualTreeHelper.GetChild(parent, childIndex));
  }

  foreach (var child in visualChildren) {
    var typedChild = child as T;
    if ((typedChild != null) && (predicate == null || predicate.Invoke(typedChild))) {
      yield return typedChild;
      if (deepSearch) {foreach (var foundVisual in FindVisualDescendants(child, predicate, true)) {
        yield return foundVisual;
      }
    } else {
      foreach (var foundVisual in FindVisualDescendants(child, predicate, deepSearch)) {
        yield return foundVisual;
      }
    }
  }

  yield break;
}
于 2012-05-17T19:38:43.273 回答
0

如果您有兴趣,这里ExpandSubTree是实际编写方式的实现(来自 Reflector)。我想你可以走相反的路。

public void ExpandSubtree()
{
    ExpandRecursive(this);
}

private static void ExpandRecursive(TreeViewItem item)
{
    if (item != null)
    {
        if (!item.IsExpanded)
        {
            item.SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.TrueBox);
        }
        item.ApplyTemplate();
        ItemsPresenter presenter = (ItemsPresenter) item.Template.FindName("ItemsHost", item);
        if (presenter != null)
        {
            presenter.ApplyTemplate();
        }
        else
        {
            item.UpdateLayout();
        }
        VirtualizingPanel itemsHost = item.ItemsHost as VirtualizingPanel;
        item.ItemsHost.EnsureGenerator();
        int index = 0;
        int count = item.Items.Count;
        while (index < count)
        {
            TreeViewItem item2;
            if (itemsHost != null)
            {
                itemsHost.BringIndexIntoView(index);
                item2 = (TreeViewItem) item.ItemContainerGenerator.ContainerFromIndex(index);
            }
            else
            {
                item2 = (TreeViewItem) item.ItemContainerGenerator.ContainerFromIndex(index);
                item2.BringIntoView();
            }
            if (item2 != null)
            {
                ExpandRecursive(item2);
            }
            index++;
        }
    }
}
于 2012-05-17T18:59:52.770 回答
0

要获取 ItemHost 并调用 EnsureGenerator,您将需要反射,因为它们是内部的:

var panel = (Panel)typeof(MultiSelector).InvokeMember("ItemsHost", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance, null, item, null);

typeof (Panel).InvokeMember("EnsureGenerator", BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance, null, panel, null);
于 2013-01-30T15:11:15.833 回答