如何使用正确的顺序获取托管元数据中的标签

在SharePoint 2010的托管元数据中,我们是可以手动指定每个分类下属的顺序的,如下图所示:

image

在代码中,可以通过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

另外,为了简单起见,我在这里面并没有考虑到术语合并、术语重复和术语否决的问题,你可以根据需要进行改动。

原文地址:https://www.cnblogs.com/erucy/p/2473913.html