拼写错误的单词的 Treeview
Resorting Treeview of misspelled words
我在 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;
}
}
我在 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;
}
}