Geeks With Blogs
SharePoint Wiki! Sharing is gaining...

I came across a requirement where I needed a way to be able to retrieve pages that have been tagged with a particular Managed Metadata (MMD) value. 

Let's say there's a MMD field called Category. And the users should be able to use the Taxonomy "picker" control to select which category value they want to filter their results by.

Let's create a WebPart to do this. Use the Web Part Tool Pane EditorPart, add it to your Web Part for filtering. The EditorPart doesn't do the actual persisting of the data, so I need to create public properties on the parent Web Part that store the selected value. My web part, "MyWebPart" has the following three public properties:

int[] CategoryWssIds
string FilterTerm
Guid CategoryTermId

The picker control should bound to the same node that my Category site column is already bound to, in the MMD tree.

Here's the code for the EditorPart class:

class Editor : EditorPart
{
private TaxonomyWebTaggingControl termPicker;

/// <summary>
/// Adds the picker control and binds it to the same term set that the
/// Category site column is bound to.
/// </summary>
protected override void CreateChildControls()
{
try
{
TaxonomyField category = SPContext.Current.Site.RootWeb.Fields["Category"] as TaxonomyField;

if (categories != null)
{
TaxonomyWebTaggingControl termPicker = new TaxonomyWebTaggingControl();
termPicker.SspId.Add(categories .SspId);
termPicker.TermSetId.Add(category.TermSetId);
termPicker.AllowFillIn = false;
termPicker.IsMulti = false;
termPicker.Width = 170;

this.Controls.Add(termPicker);
}
}
catch (Exception e)
{
//Display error message
}
}

/// <summary>
/// Takes the term that was selected by the user in the picker control, and
/// saves its properties to the parent web part's properties.
/// </summary>
/// <returns>A flag indicating whether the changes could be saved or not.</returns>
public override bool ApplyChanges()
{
try
{
termPicker = (TaxonomyWebTaggingControl)this.Controls[0];

//Evaluate if the user has picked a term
string selectedTaxValue = termPicker.Text;
int separatorIndex = selectedTaxValue.IndexOf("|");
if (selectedTaxValue != string.Empty && separatorIndex != -1)
{
//If the user has selected a term, save that term and its lookup list id (or ids, if there are child terms)
//to the parent web part. (The lookup ids are the ids of the term in the TaxonomyHiddenList in the current
//site collection.)
TaxonomyField category = SPContext.Current.Site.RootWeb.Fields["Category"] as TaxonomyField;
Guid termSetId = category.TermSetId;
TaxonomySession session = new TaxonomySession(SPContext.Current.Site);
Guid termId = new Guid(selectedTaxValue.Substring(separatorIndex + 1));
string filterTerm = selectedTaxValue.Substring(0, separatorIndex);
int[] wssIds = TaxonomyField.GetWssIdsOfTerm(SPContext.Current.Site, session.TermStores[0].Id, termSetId, termId, true, 100);
if (wssIds.Length > 0)
{
MyWebPart myWebPart = this.WebPartToEdit as MyWebPart;
myWebPart.CateogryWssIds = wssIds;
myWebPart.FilterTerm = filterTerm;
myWebPart.CategoryTermId = termId;
myWebPart.SaveChanges();
}
else
{
return false;
}
}
}
catch (Exception e)
{
return false;
}

return true;
}

/// <summary>
///Retrieves the properties stored in the web part and sets the value of the
/// metadata picker control based on them.
/// </summary>
public override void SyncChanges()
{
EnsureChildControls();

termPicker = (TaxonomyWebTaggingControl)this.Controls[0];
MyWebPart myWebPart = this.WebPartToEdit as MyWebPart;

if (myWebPart.CateogryWssIds != null &&
myWebPart.CateogryWssIds.Length != 0 &&
termPicker.Text == string.Empty)
{
termPicker.Text = String.Format("{0}|{1}", myWebPart.FilterTerm,
myWebPart.CategoryTermId.ToString());
}
}
}

Now that I have an EditorPart, I need to add it to MyWebPart. I can do it like this:

public override EditorPartCollection CreateEditorParts()
{
Editor editor = new Editor();
editor.ID = this.ID + "_Editor";
editor.Title = "Filter Term";
List editors = new List();
editors.Add(editor);
return new EditorPartCollection(editors);
}

Add the following method to make sure the changes made by the Editor part get persisted to the web part:

public void SaveChanges()
{
this.SetPersonalizationDirty();
}

When it's time to build my CAML query string, I do it like this:

StringBuilder values = new StringBuilder();
for (int i = 0; i < categoryWssIds.Length; i++)
{
values.Append("<Value type='Integer'>");
values.Append(categoryWssIds[i].ToString());
values.Append("</Value>");
}

string query = String.Format(@"<Where>
<In>
<FieldRef name="Category" LookupId="TRUE"/><Values>{0}</Values>
</In>
</Where>", values.ToString());

One thing to keep in mind is that this is querying the hidden list in the current site collection that stores all the MMD values that have been used. So, if you haven't used a particular term yet anywhere in your site, the GetWssIdsOfTerm method won't give you anything back.
Posted on Thursday, April 26, 2012 10:56 AM | Back to top


Comments on this post: Web Part to execute CAML Query - Using 'Managed Metadata' entered user

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © KunaalKapoor | Powered by: GeeksWithBlogs.net