如何使用正确的顺序获取托管元数据中的标签
在SharePoint 2010的托管元数据中,我们是可以手动指定每个分类下属的顺序的,如下图所示:
在代码中,可以通过TermSet或者Term的CustomSortOrder属性获取到在这个地方设置的顺序(用冒号分隔的TermId)。
如果没有设置顺序的话,用TermSet.Terms或者Term.Terms拿到其中的子级标签(理论上应该是按照字母顺序排的,但我们曾经遇到过这个顺序是乱的,原因不明)
但是这里面有一个很大的问题:如果自定义了排序之后,再添加了新的节点的话,在CustomSortOrder这个属性里面是不会包含这几个新节点的,管理员必须再到排序界面重新保存一下才行,如果忘了的话,嗯……
我们在项目里面就遇到了这样的问题,最后我写了一个扩展类,给TermSet和Term各增加了一个扩展方法:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using Microsoft.SharePoint.Taxonomy;
6:
7: namespace Erucy.Utilities
8: {
9: public static class TaxonomyExtension
10: {
11: static List<Term> GetTermsByOrderInternal(TermCollection terms, string customOrder)
12: {
13: List<Term> result = new List<Term>(terms.Count);
14: Dictionary<string, Term> idMap = new Dictionary<string, Term>();
15: Dictionary<string, Term> nameMap = new Dictionary<string, Term>();
16: Dictionary<string, string> idNameMap = new Dictionary<string, string>();
17: foreach (Term term in terms)
18: {
19: nameMap[term.Name] = term;
20: idMap[term.Id.ToString()] = term;
21: idNameMap[term.Id.ToString()] = term.Name;
22: }
23:
24: // Custom Order
25: if (!string.IsNullOrEmpty(customOrder))
26: {
27: string[] termIds = customOrder.Split(':');
28: foreach (string termId in termIds)
29: {
30: if (idMap.ContainsKey(termId))
31: {
32: result.Add(idMap[termId]);
33: idNameMap.Remove(termId);
34: }
35: }
36: }
37:
38: // Others
39: List<string> otherNames = new List<string>(idNameMap.Values);
40: otherNames.Sort();
41: foreach (string termName in otherNames)
42: result.Add(nameMap[termName]);
43:
44: return result;
45: }
46:
47: public static IEnumerable<Term> GetTermsByOrder(this TermSet termSet)
48: {
49: return GetTermsByOrderInternal(termSet.Terms, termSet.CustomSortOrder);
50: }
51:
52: public static IEnumerable<Term> GetTermsByOrder(this Term term)
53: {
54: return GetTermsByOrderInternal(term.Terms, term.CustomSortOrder);
55: }
56: }
57: }
其中的GetTermsByOrderInternal是核心方法,思想就是先按照CustomSortOrder排序(如果有定义的话),然后把剩下的按照名称排个序,最后返回IEnumerable<Term>类型。
在使用的时候,就可以这样来用了:
1: TermSet mySet;
2: // Get TermSet
3: // ...
4: foreach(Term term in mySet.GetTermsByOrder())
5: {
6: Console.WriteLine(term.Name);
7: foreach(Term childTerm in term.GetTermsByOrder())
8: Console.WriteLine("\t" + childTerm.Name);
9: }
当然,为了能够让你的程序能够识别扩展方法,不要忘了using Erucy.Utilities,嗯。
在这个地方可以下载这个扩展文件,欢迎拿去直接用:点我点我:TaxonomyExtension.zip
另外,为了简单起见,我在这里面并没有考虑到术语合并、术语重复和术语否决的问题,你可以根据需要进行改动。