刷新后展开ViewTree

时间:2018-02-14 12:59:17

标签: c# wpf visual-studio-extensions

我有一个viewtree是数据绑定到xml文档,当文档被保存时我在datacontext上调用refresh并且ViewTree崩溃了,我真的希望viewtree不会折叠,所以我正在尝试编写一个解包的函数它再次。 在这里,我试图使用xml元素的xpath来访问treeviewitems,但是我只能得到root对象,我怀疑是因为'ContainerFromItem'要求它们在那里可见而不是逻辑上存在? 但我不知道怎么做。

这是在刷新datacontext后调用的方法

private void UnpackOpened(object sender, EventArgs e)
{
    foreach (var node in nodes)
    {
        var pathStrings = node.Path.Split('/').ToList();
        pathStrings.RemoveAll(string.IsNullOrEmpty);
        for (int i = 0; i < pathStrings.Count; i++)
        {
            pathStrings[i] = pathStrings[i].Replace("{", "").Replace("}", "");
            pathStrings[i] = pathStrings[i].Replace("[", "|").Replace("]", "");
        }

        ExpandTree(OutlineWindowInstance.TreeItems.ItemContainerGenerator, pathStrings, 0);
    }
}

这是一个递归函数,它应该遍历所有以前打开的treeviewitems并在现在刷新的树中展开它们。

void ExpandTree(ItemContainerGenerator itemses, List<string> treeNodes, int step)
{
    var name = treeNodes[step].Split('|')[0];
    var number = int.Parse(treeNodes[step].Split('|')[1])-1;
    var selected = itemses.Items.Cast<XmlElement>().Where(x => x.LocalName == name).ToList()[number];
    var selectedItem =((TreeViewItem) 
    //this is the line that is failing to do what I had hoped it would do
    itemses.ContainerFromItem(selected)); 
    if(selectedItem == null) return;
    selectedItem.IsExpanded = true;

    step++; 
    if (treeNodes.Count > step)
    {
        ExpandTree(selectedItem.ItemContainerGenerator, treeNodes, step);
    }
}

1 个答案:

答案 0 :(得分:0)

所以我设法解决了这个问题。 首先,我有一个所有当前文档的列表,为此我创建了以下类,它处理与它所代表的文档的节点有关的所有事情

public class OpennedDocument
{
    public string DocName { get; set; }
    public List<string> ExpandedNodes;
    public bool IsRefreshing { get; set; }

    public void AddExpandedNode(string path)
    {
        if (IsRefreshing) return; //This stops it from registering a node during automatic expansion (after a refresh)
        ExpandedNodes.RemoveAll(path.Contains);
        ExpandedNodes.Add(path);
    }

    public void RemoveExpandedNode(string path)
    {
        var index = path.LastIndexOf("/", StringComparison.Ordinal);

        if(IsRefreshing)return;
        ExpandedNodes.RemoveAll(x => x.Contains(path));

        path = path.Remove(index);
        if(!string.IsNullOrEmpty(path))
            ExpandedNodes.Add(path);
    }
}

这些方法位于通用管理器脚本中,并确保在刷新之前打开的树视图中的所有节点随后再次打开。

private void UnpackOpened(object sender, EventArgs e)
{
    var currentDoc = Documents.SingleOrDefault(x => x.DocName == dte.ActiveDocument.FullName);
    if (currentDoc == null) return;
    currentDoc.IsRefreshing = true;

    for (var index = 0; index < currentDoc.ExpandedNodes.Count; index++)
    {
        var node = currentDoc.ExpandedNodes[index];
        var pathStrings = node.Split('/').ToList();
        pathStrings.RemoveAll(string.IsNullOrEmpty);
        for (int i = 0; i < pathStrings.Count; i++)
        {
            pathStrings[i] = pathStrings[i].Replace("{", "").Replace("}", "");
            pathStrings[i] = pathStrings[i].Replace("[", "|").Replace("]", "");
        }

        ExpandTree(OutlineWindowInstance.TreeItems.ItemContainerGenerator, pathStrings, 0,
            OutlineWindowInstance.TreeItems);
    }

    currentDoc.IsRefreshing = false;
}

void ExpandTree(ItemContainerGenerator itemses, List<string> treeNodes, int step, ItemsControl last)
{
    while (true)
    {
        last.UpdateLayout();
        var name = treeNodes[step].Split('|')[0];
        var number = int.Parse(treeNodes[step].Split('|')[1]) - 1;
        var selected = itemses.Items.Cast<XmlElement>().Where(x => x.LocalName == name).ToList()[number];
        var selectedItem = ((TreeViewItem) itemses.ContainerFromItem(selected));
        if (selectedItem == null) return;
        selectedItem.IsExpanded = true;

        step++;
        if (treeNodes.Count > step)
        {
            itemses = selectedItem.ItemContainerGenerator;
            last = selectedItem;
            continue;
        }
        break;
    }
}