我正在尝试向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比无用的步骤高出半步。我可以在它为真时将其设置为false,并且它不会折叠超过所选的最高级别。
谢谢!
答案 0 :(得分:1)
如果您有兴趣,这里是实现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++;
}
}
}
答案 1 :(得分:1)
我实现扩展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;
}
答案 2 :(得分: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);
}
}
}
}
答案 3 :(得分:1)
要获取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);