I came up with a few criteria for looking at our current site columns and deciding if they would fit as managed metadata columns based on our goal of a better user experience and more available and relevant search results:
- The column must have multiple valid values
- Values for the column must be at least partly defined
- There is a good chance that the values for this column will be expanded upon in the future
- Users may want to define more than one pre-defined value in the same column
This list may not be complete, but it gave me a good place to start from.
Before creating any of my fields, content types, or lists I made a feature that would deploy all of the terms I had defined for these columns. I separated the values out into separate term sets for each column and placed all of these term sets in a term group that is housing all of the term sets we are using on our extranet. Bob Moore has a great blog post describing how to do this already so I won’t repost what he has written.
I created a new empty element to house my fields and then went to work defining the generic fields from across the site. Then i defined all of my managed metadata fields. To not bore you with a ton of code I will follow the “Bug Type” field I created from start to finish. Here is the XML that defines the field:
<Field ID="{64115AE4-61C6-4AF5-B96B-5A6712880BE4}" Name="BugType" ShowField="Term1033" StaticName="BugType" Group="Extranet_SiteColumns" Type="TaxonomyFieldType" DisplayName="Type" EnforceUniqueValues="FALSE" Required="TRUE"/>
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode, .ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode pre
{font-size:small;color:black;font-family:consolas, “Courier New”, courier, monospace;background-color:#ffffff;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode pre
{margin:0em;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .rem
{color:#008000;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .kwrd
{color:#0000ff;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .str
{color:#006080;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .op
{color:#0000c0;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .preproc
{color:#cc6633;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .asp
{background-color:#ffff00;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .html
{color:#800000;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .attr
{color:#ff0000;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .alt
{background-color:#f4f4f4;width:100%;margin:0em;}
.ExternalClassB41FEC5C48F44F9A932A3E0ABE1D8213 .csharpcode .lnum
{color:#606060;}
One thing that is really important to remember is to always have the ‘EnforceUniqueValues’ property set to false. I learned the hard way that this property makes the field a key for the item, so all values would have to be unique between all items in a list. Another important property is the ‘ShowField’ property, I have only seen it set to ‘Term1033’, so this is how I set it for all of my managed metadata fields.
After creating the field I added an event receiver this feature that hooks up all of my managed metadata fields to the term sets I created for them. I pulled out the code for all of my other managed metadata columns, but you should get the gist.
public override void FeatureActivated(SPFeatureReceiverProperties properties) { string termGroupName = "ExtranetTermSets"; string BUG_TYPE = "BugType"; //Dictionary of fields and their guids Dictionary<string, string> termSetFieldGuid = new Dictionary<string, string>(); termSetFieldGuid.Add(BUG_TYPE, "64115AE4-61C6-4AF5-B96B-5A6712880BE4"); SPSite site = SPContext.Current.Site; //hook up all managed metadata columns to terms TaxonomySession session = new TaxonomySession(site); //TermStores[0] is the default, you can also pass a string of the name of the term store you want to use TermStore termstore = session.TermStores[0]; Group group = termstore.Groups[termGroupName]; foreach (KeyValuePair<string, string> fieldSet in termSetFieldGuid) { TermSet pbxTermSet = group.TermSets[fieldSet.Key]; TaxonomyField mmField = (TaxonomyField)site.OpenWeb().Fields[new Guid(fieldSet.Value)]; mmField.SspId = termstore.Id; mmField.TermSetId = pbxTermSet.Id; mmField.IsPathRendered = false; mmField.Update(); } }
And there you have it. I also created content types with these fields and custom lists using those content types. Adding these managed metadata columns to a content type is exactly the same as any other column.