在树视图列表中隐藏节点.在 C# 中 [英] Hide Node in Treeview List. in C#

查看:47
本文介绍了在树视图列表中隐藏节点.在 C# 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 VS 2005 C#,在一个未完成的 WinForm 上工作.

I am using VS 2005 C#, working on an unfinished WinForm.

我已将 XML 解析为树视图列表,但遇到了一些问题.我想知道是否有办法隐藏/过滤/删除名称中包含_this_text"的某个节点,而不必依赖文本框.

I have parsed an XML to a treeview listing but I'm encountering some problems. I wanna know if there's a way to hide/filter/remove a certain node containing a "_this_text" in its name without having to depend on a textbox.

这就是我对这个程序所拥有的(感谢那些帮助我开发这个程序的人):

This is what I have for the program (kudos to those who helped me develop this):

#region "***** XML Parsing *****"
    private void Form1_Load_1(object sender, EventArgs e)
    {
        // Initialize the controls and the form.
        //label1.Text = "File Path";
        textBox2.Text = Application.StartupPath + "\\Continental.vsysvar";
        //button6.Text = "XML";
        //this.Text = "Software Validation";
    }

    private TreeNode selectedNode = null;

    private void button6_Click(object sender, EventArgs e)
    {
        try
        {
            // SECTION 1. Create a DOM Document and load the XML data into it.
            XmlDocument dom = new XmlDocument();
            dom.Load(textBox2.Text);

            // SECTION 2. Initialize the TreeView control.
            treeView1.Nodes.Clear();
            /*treeView1.Nodes.Add(new TreeNode(dom.DocumentElement.Name));
            TreeNode tNode = new TreeNode();
            tNode = treeView1.Nodes[0];*/

            foreach (XmlNode node in dom.DocumentElement.ChildNodes)
            {
                if (node.Name == "namespace" && node.ChildNodes.Count == 0 && string.IsNullOrEmpty(GetAttributeText(node, "name")))
                    continue;
                AddNode(treeView1.Nodes, node);
            }

            treeView1.ExpandAll();
        }
        /* catch (XmlException xmlEx)
         {
             MessageBox.Show(xmlEx.Message);
         }*/
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void LoadTreeFromXmlDocument(XmlDocument dom)
    {
        try
        {
            // SECTION 2. Initialize the TreeView control.
            treeView1.Nodes.Clear();

            // SECTION 3. Populate the TreeView with the DOM nodes.
            foreach (XmlNode node in dom.DocumentElement.ChildNodes)
            {
                if (node.Name == "namespace" && node.ChildNodes.Count == 0 && string.IsNullOrEmpty(GetAttributeText(node, "name")))
                    continue;
                AddNode(treeView1.Nodes, node);
            }

            treeView1.ExpandAll();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    static string GetAttributeText(XmlNode inXmlNode, string name)
    {
        XmlAttribute attr = (inXmlNode.Attributes == null ? null : inXmlNode.Attributes[name]);
        return attr == null ? null : attr.Value;
    }

    private void AddNode(TreeNodeCollection nodes, XmlNode inXmlNode)
    {
        if (inXmlNode.HasChildNodes)
        {
            string text = GetAttributeText(inXmlNode, "name");
            if (string.IsNullOrEmpty(text))
                text = inXmlNode.Name;
            TreeNode newNode = nodes.Add(text);
            XmlNodeList nodeList = inXmlNode.ChildNodes;
            for (int i = 0; i <= nodeList.Count - 1; i++)
            {
                XmlNode xNode = inXmlNode.ChildNodes[i];
                AddNode(newNode.Nodes, xNode);
            }
        }
        else
        {
            // If the node has an attribute "name", use that.  Otherwise display the entire text of the node.
            string text = GetAttributeText(inXmlNode, "name");
            if (string.IsNullOrEmpty(text))
                text = (inXmlNode.OuterXml).Trim();
            TreeNode newNode = nodes.Add(text);
        }
    }
    #endregion

这是 XML 文件的摘录,因为它很长:

And here's an excerpt of the XMl file since it's quite long:

    <?xml version="1.0" encoding="utf-8"?>
<systemvariables version="4">
  <namespace name="" comment="">
    <namespace name="_01_Test_Preparation" comment="">
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_02_Shipping_Status_Check" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_02_Shipping_Status_Check_start" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_01_Get_Dem_ID" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_01_Get_Dem_ID_start" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_04_ECU_Version_Check_start" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_03_Test_Run_Init" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_04_ECU_Version_Check" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_05_DEM_Reader" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_03_Test_Run_Init_start" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
      <variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="_01_05_DEM_Reader_start" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="4" maxValuePhys="4" />
    </namespace>

我真正想要完成的是隐藏或过滤名称中包含此文本_start"的节点.因此,所有名称中包含_this_start"的节点将对用户隐藏.我已经读过,从技术上讲,启用或禁用可见性是不可能的,而是将文本和诸如此类的东西变成灰色.

What I really want to accomplish is to hide or filter the nodes containing this text "_start" found in their name. So all nodes containing "_this_start" in their name would be hidden from the user. I've read that it is not technically possible to enable or disable visibility but instead gray out the text and whatnot.

提前致谢.

推荐答案

从您的问题中不清楚过滤器是静态的还是可由用户配置的.假设可以动态配置过滤器,您可以做的是在过滤器更改时(重新)从 XML 加载树、回收现有节点、根据需要创建新节点以及删除过滤节点.(当然,如果过滤器是静态的,这也适用.)

It's not clear from your question whether the filter is static or can be configured by the user. Assuming that the filter can be configured dynamically, what you could do is to (re)load the tree from the XML whenever the filter changes, recycling existing nodes, creating new nodes as needed, and deleting filtered nodes. (Of course, this also works if the filter is static.)

首先,提取一个辅助方法来从 XML 重新填充树,在适当的时候按名称回收节点:

First, extract a helper method to repopulate a tree from XML, recycling nodes by name when appropriate:

public delegate string GetString<T>(T input); // No Func<T, TResult> in c# 2.0

public static class XmlTreeViewHelper
{
    public static void AddOrMergeNodes(TreeNodeCollection treeNodeCollection, XmlNodeList xmlNodeList, GetString<XmlNode> getNodeName, GetString<XmlNode> getNodeText, Predicate<XmlNode> filter)
    {
        Dictionary<string, List<TreeNode>> dict = ToNodeDictionary(treeNodeCollection);
        int index = 0;
        foreach (XmlNode inXmlNode in xmlNodeList)
        {
            AddOrMergeNode(treeNodeCollection, inXmlNode, ref index, getNodeName, getNodeText, filter, dict);
        }

        foreach (List<TreeNode> list in dict.Values)
            foreach (TreeNode leftover in list)
            {
                treeNodeCollection.Remove(leftover);
            }
    }

    static bool IsNodeAtIndex(TreeNodeCollection nodes, TreeNode node, int index)
    {
        // Avoid n-squared nodes.IndexOf(node).
        if (index < 0 || index >= nodes.Count)
            return false;
        return nodes[index] == node;
    }

    static void AddOrMergeNode(TreeNodeCollection treeNodeCollection, XmlNode inXmlNode, ref int index, GetString<XmlNode> getNodeName, GetString<XmlNode> getNodeText, Predicate<XmlNode> filter, Dictionary<string, List<TreeNode>> dict)
    {
        if (filter != null && !filter(inXmlNode))
            return;

        string treeName = getNodeName(inXmlNode);
        string treeText = (getNodeText == null ? treeName : getNodeText(inXmlNode));

        bool added = false;

        TreeNode treeNode;
        if (!DictionaryExtensions.TryRemoveFirst(dict, treeName, out treeNode))
        {
            treeNode = new TreeNode();
            treeNode.Name = treeName;
            treeNode.Text = treeText;
            added = true;
            treeNodeCollection.Insert(index, treeNode);
        }
        else
        {
            if (!IsNodeAtIndex(treeNodeCollection, treeNode, index))
            {
                treeNodeCollection.Remove(treeNode);
                treeNodeCollection.Insert(index, treeNode);
            }
        }

        index++;

        if (treeNode.Text != treeText)
            treeNode.Text = treeText;

        if (inXmlNode.HasChildNodes)
            AddOrMergeNodes(treeNode.Nodes, inXmlNode.ChildNodes, getNodeName, getNodeText, filter);
        else
            treeNode.Nodes.Clear();

        if (added)
            treeNode.ExpandAll();
    }

    /// <summary>
    /// Returns a dictionary of tree nodes by node name.
    /// </summary>
    /// <param name="nodes"></param>
    /// <returns></returns>
    static Dictionary<string, List<TreeNode>> ToNodeDictionary(TreeNodeCollection nodes)
    {
        Dictionary<string, List<TreeNode>> dict = new Dictionary<string, List<TreeNode>>();
        foreach (TreeNode node in nodes)
            DictionaryExtensions.Add(dict, node.Name, node);
        return dict;
    }
}

public static class DictionaryExtensions
{
    public static void Add<TKey, TValueList, TValue>(IDictionary<TKey, TValueList> listDictionary, TKey key, TValue value)
        where TValueList : IList<TValue>, new()
    {
        if (listDictionary == null)
            throw new ArgumentNullException();
        TValueList values;
        if (!listDictionary.TryGetValue(key, out values))
            listDictionary[key] = values = new TValueList();
        values.Add(value);
    }

    public static bool TryGetValue<TKey, TValueList, TValue>(IDictionary<TKey, TValueList> listDictionary, TKey key, int index, out TValue value)
        where TValueList : IList<TValue>
    {
        TValueList list;
        if (!listDictionary.TryGetValue(key, out list))
            return Returns.False(out value);
        if (index < 0 || index >= list.Count)
            return Returns.False(out value);
        value = list[index];
        return true;
    }

    public static bool TryRemoveFirst<TKey, TValueList, TValue>(IDictionary<TKey, TValueList> listDictionary, TKey key, out TValue value)
        where TValueList : IList<TValue>
    {
        TValueList list;
        if (!listDictionary.TryGetValue(key, out list))
            return Returns.False(out value);
        int count = list.Count;
        if (count > 0)
        {
            value = list[0];
            list.RemoveAt(0);
            if (--count == 0)
                listDictionary.Remove(key);
            return true;
        }
        else
        {
            listDictionary.Remove(key); // Error?
            return Returns.False(out value);
        }
    }
}

public static class Returns
{
    public static bool False<TValue>(out TValue value)
    {
        value = default(TValue);
        return false;
    }
}

接下来,动态(重新)加载 XML 并应用任何合适的过滤器:

Next, dynamically (re)load the XML and apply whatever filter is appropriate:

    private void ReloadTreeFromXmlDocument(XmlDocument dom)
    {
        treeView1.BeginUpdate();
        try
        {
            XmlTreeViewHelper.AddOrMergeNodes(treeView1.Nodes, dom.DocumentElement.ChildNodes, GetTreeNodeName, GetTreeNodeText, FilterNode);
        }
        finally
        {
            treeView1.EndUpdate();
        }
    }

    static string GetTreeNodeName(XmlNode inXmlNode)
    {
        string text = GetAttributeText(inXmlNode, "name");
        if (string.IsNullOrEmpty(text))
            text = inXmlNode.Name;
        return text;
    }

    static string GetTreeNodeText(XmlNode inXmlNode)
    {
        string text = GetAttributeText(inXmlNode, "name");
        if (string.IsNullOrEmpty(text))
        {
            if (inXmlNode.HasChildNodes)
            {
                text = inXmlNode.Name;
            }
            else
            {
                text = (inXmlNode.OuterXml).Trim();
            }
        }
        return text;
    }

    string filter = "_start"; // Reload when this changes

    bool FilterNode(XmlNode inXmlNode)
    {
        return FilterNode(inXmlNode, filter /*filterComboBox.Text*/);
    }

    bool FilterNode(XmlNode inXmlNode, string nodeNameFilter)
    {
        if (inXmlNode.Name == "namespace" && inXmlNode.ChildNodes.Count == 0 && string.IsNullOrEmpty(GetAttributeText(inXmlNode, "name")))
            return false;
        if (!string.IsNullOrEmpty(nodeNameFilter))
        {
            string text = GetTreeNodeText(inXmlNode);
            if (text.Contains(nodeNameFilter))
                return false;
        }
        return true;
    }

    static string GetAttributeText(XmlNode inXmlNode, string name)
    {
        XmlAttribute attr = (inXmlNode.Attributes == null ? null : inXmlNode.Attributes[name]);
        return attr == null ? null : attr.Value;
    }

将我的解决方案向后移植到 .Net 2.0 后,这就是我得到的:

After backporting my solution to .Net 2.0, this is what I get:

这篇关于在树视图列表中隐藏节点.在 C# 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆