对拼写错误的单词进行排序树视图
本文关键字:排序 视图 单词进 错误 | 更新日期: 2023-09-27 18:36:10
我在 C# 中有一个实用程序,它可以解析源代码并创建一个 xml 报告,其中包含带引号的文本字符串中的所有拼写错误的单词、文件以及它们在文件中出现的位置。我有另一个实用程序可以读取此xml文件并将其加载到树视图中,该树视图如下所示:
MisspelledWords
|
|___badd
| |__Suggestions
| | |__bad
| |
| |__Locations
| |__Location
| |__FileName
| | |__ C:'Workspaces'MyProject'Project1'program.cs
| |
| |__LineNumber
| | |
| | |_ 31
| |
| |__Original Line
|
|___spellling
| |__Suggestions
| | |__spelling
| |
| |__Locations
| |__Location
| |__FileName
| | |__ C:'Workspaces'MyProject'Project1'program.cs
| |
| |__LineNumber
| | |
| | |_ 55
| |
| |__Original Line
加载到树视图中的所有内容第一次都成功排序,但是当我清除树视图,重新加载它并排序(treeview1.sort)时,所有子节点都添加到级别1的最后一个拼写错误的单词节点中。
这是我当前要加载和排序的代码片段。
private void button1_Click(object sender, EventArgs e)
{
if (!bTreeLoaded)
{
//Add the "Ignored" Top Level node.
TreeNode ignoreNode = new TreeNode("Ignored List");
treeView1.Nodes.Add(ignoreNode);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(textBox1.Text);
TreeNode misspelledWordsNode = new TreeNode(xmldoc.DocumentElement.Name);
treeView1.Nodes.Add(misspelledWordsNode);
AddNode(xmldoc.DocumentElement, misspelledWordsNode);
treeView1.Sort();
bTreeLoaded = true;
}
else
{
MessageBox.Show("Data has already been loaded");
}
}
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
XmlNode xNode;
TreeNode tNode;
XmlNodeList nodeList;
int i = 0;
if (inXmlNode.HasChildNodes)
{
nodeList = inXmlNode.ChildNodes;
for (i = 0; i <= nodeList.Count - 1; i++)
{
xNode = inXmlNode.ChildNodes[i];
inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = inTreeNode.Nodes[i];
AddNode(xNode, tNode);
}
}
else
{
inTreeNode.Text = (inXmlNode.OuterXml).Trim();
}
}
private void button2_Click(object sender, EventArgs e)
{
treeView1.Nodes.Clear();
bTreeLoaded = false;
}
我的 XML 文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<MisspelledWords xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<badd>
<Suggestions>
<Suggestion>bad</Suggestion>
</Suggestions>
<Locations>
<Location>
<FileName>C:'Workspaces'AHLTA'Current'VB6'global.bas</FileName>
<LineNumber>31</LineNumber>
<OriginalLine>s = "badd spellling"</OriginalLine>
</Location>
</Locations>
</badd>
</MisspelledWords>
我无法重现您的问题,因为您没有显示如何在重新加载之前清除预先存在的节点树。 在显示的代码中,您只是不允许在树中重新加载节点。
通常,如果要将树更新为某些分层数据,则需要合并每个级别的列表,使用节点的名称或标记对节点进行键控。 例如,以下内容似乎适用于您的 XML:
private void LoadXML_Click(object sender, EventArgs e)
{
treeView1.BeginUpdate();
try
{
//Add the "Ignored" Top Level node.
if (!treeView1.Nodes.ContainsKey("Ignored List"))
treeView1.Nodes.Add(new TreeNode { Name = "Ignored List", Text = "Ignored List" });
var xmldoc = GetXmlDocument(); // From your UI
int changed = AddOrMergeNodes(xmldoc);
Debug.WriteLine("Added or removed " + changed + " nodes");
if (changed > 0)
{
treeView1.ExpandAll();
treeView1.Sort();
}
}
finally
{
treeView1.EndUpdate();
}
treeView1.Focus();
}
private void clearXML_Click(object sender, EventArgs e)
{
treeView1.Nodes.Clear();
}
static Dictionary<string, List<TreeNode>> ToNodeDictionary(TreeNodeCollection nodes)
{
return nodes.Cast<TreeNode>().Aggregate(new Dictionary<string, List<TreeNode>>(), (d, n) => { d.Add(n.Name, n); return d; });
}
int AddOrMergeNodes(XmlDocument xmldoc)
{
var dict = ToNodeDictionary(treeView1.Nodes);
return AddOrMergeNode(treeView1.Nodes, dict, xmldoc.DocumentElement);
}
static int AddOrMergeNodes(TreeNodeCollection treeNodeCollection, XmlNodeList xmlNodeList)
{
int changed = 0;
var dict = ToNodeDictionary(treeNodeCollection);
foreach (XmlNode inXmlNode in xmlNodeList)
{
changed += AddOrMergeNode(treeNodeCollection, dict, inXmlNode);
}
foreach (var leftover in dict.Values.SelectMany(l => l))
{
treeNodeCollection.Remove(leftover);
changed++;
}
return changed;
}
static int AddOrMergeNode(TreeNodeCollection treeNodeCollection, Dictionary<string, List<TreeNode>> dict, XmlNode inXmlNode)
{
int changed = 0;
var name = inXmlNode.Name;
TreeNode node;
if (!dict.TryRemoveFirst(name, out node))
{
node = new TreeNode { Name = name, Text = name };
treeNodeCollection.Add(node);
changed++;
}
Debug.Assert(treeNodeCollection.Contains(node), "treeNodeCollection.Contains(node)");
if (inXmlNode.HasChildNodes)
{
var text = name;
if (node.Text != text)
node.Text = name;
changed += AddOrMergeNodes(node.Nodes, inXmlNode.ChildNodes);
}
else
{
var text = (inXmlNode.OuterXml).Trim();
if (node.Text != text)
node.Text = text;
node.Nodes.Clear();
}
return changed;
}
然后是一些处理列表字典的扩展方法,为方便起见:
public static class DictionaryExtensions
{
public static void Add<TKey, TValueList, TValue>(this 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>(this 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>(this 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);
var 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;
}
}