Step 3: Create a Web Control to Display Related Items
Next create a Web control class to display search results on your Web site. In this solution there are three Web controls:
- RelatedItems.cs
- SearchResults.cs
- Facet.cs
In this blog post we will only create the first control, RelatedItems.cs and provide the code used to create the facet control.
How to Create a Related Items Web Control
RelatedItems.cs
The purpose of the related items control is to trigger a query that fetches content from the search indexes. It uses the Searcher and the Query Runner classes to return a list of items and then formats the list and displays the results as related items in the side bar of the appropriate product pages.
To create a related items control:
1. Include the following namespaces:
namespace Starterkit.WebControls { using System; using System.Web.UI; using Sitecore.Data.Items; using Sitecore.Links; using System.Collections.Generic; using System.Linq; using Sitecore.Data; using Sitecore.Data.Fields; using Sitecore.Diagnostics; using Sitecore.Training.Index;
2. Name this Web control RelatedItems.
public class RelatedItems : Sitecore.Web.UI.WebControl
3. When you create a class that inherits from a Web control you always need a DoRender method. Create a DoRender method to control the presentation of the related items list. The following code extract shows the entire method.
protected override void DoRender(HtmlTextWriter output) { var categories = from relatedItem in GetAllRelations() group relatedItem by GetDisplayNameById(relatedItem.ParentID) into g select new { CategoryName = g.Key, Items = g }; if (categories.Count() > 0) { //<div id="relatedItems"> output.AddAttribute(HtmlTextWriterAttribute.Id, "relatedItems"); output.RenderBeginTag(HtmlTextWriterTag.Div); //<h2> output.RenderBeginTag(HtmlTextWriterTag.H2); output.Write("Related Categories"); //</h2> output.RenderEndTag(); //<ul> output.RenderBeginTag(HtmlTextWriterTag.Ul); foreach (var category in categories) { //<li> output.RenderBeginTag(HtmlTextWriterTag.Li); output.Write(String.Format("{0} ({1}):", category.CategoryName, category.Items.Count())); //</li> output.RenderEndTag(); //<ul> output.RenderBeginTag(HtmlTextWriterTag.Ul); foreach (var item in category.Items) { //<li> output.RenderBeginTag(HtmlTextWriterTag.Li); //<a href='/item.aspx' output.AddAttribute(HtmlTextWriterAttribute.Href, LinkManager.GetItemUrl(item)); output.RenderBeginTag(HtmlTextWriterTag.A); output.Write(item.DisplayName); //</a> output.RenderEndTag(); //</li> output.RenderEndTag(); } //</ul> output.RenderEndTag(); } //</ul> output.RenderEndTag(); //</div> output.RenderEndTag(); } }
Create a method called GetAllRelations.
protected IEnumerable<Item> GetAllRelations()
This method goes to the multi-list field on the item and fetches all items that are marked as related by reading the value of the multi-list field.
It then creates an instance of the Searcher and calls the Searcher GetRelatedItems byField method which triggers the Searcher and Query Runner.
4. In the GetAllRelations method, use comments to select a Searcher method. Add or remove comments so that only one method can be run at any one time:
//relatedItems.AddRange(searcher.GetItemsByFullTextQuery(ItemIds)); relatedItems.AddRange(searcher.GetRelatedItemsByField(ItemIds, fieldName, true)); //relatedItems.AddRange(searcher.GetRelatedItems(ItemIds));
This enables you to easily change the way the control interacts with the Searcher.
5. Create a method called GetDirectItemRelations(string fieldName)
protected List<Item> GetDirectItemRelations(string fieldName) { var directItemRelations = new List<Item>(); foreach (var itemId in ItemIds.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries)) { var item = Sitecore.Context.Database.GetItem(itemId); if (item != null && item.Fields[fieldName] != null && (FieldTypeManager.GetField(item.Fields[fieldName]) is MultilistField)) { MultilistField relatedItemsField = item.Fields[fieldName]; directItemRelations.AddRange(relatedItemsField.GetItems()); } } return directItemRelations; } return directItemRelations; }
Get all related items and return a list of GUIDS that are pipe separated. Sitecore uses pipe separated lists in the Related Items field to separate GUIDS. In the Content Editor View tab, if you select the raw values field, you can see the pipe separated GUIDS in the RelatedItems field.
6. Create a method called GetDisplayNameById(ID itemId).
This method gets the title or display name for the selected item from the title field and displays it in the control.
| Related Items Web control |
7. Save and compile your new Web control.
Facet.cs
This control adds the refinements that display Category and Brand Name above the related items control.
The Facet Web control fetches items from the Content Editor, content tree and then gets the URLs of each item. Then it constructs a query in the address bar of the browser.
For example:
http://<your site>/en/Standard-Items/Search-Results.aspx?search=desk
Code extract to show how the refinements query is constructed:
{ string url = LinkManager.GetItemUrl(Sitecore.Context.Item); var queryStringDictionary = WebUtil.ParseQueryString(WebUtil.GetQueryString()); if(queryStringDictionary.ContainsKey(FieldName)) queryStringDictionary.Remove(FieldName); return WebUtil.AddQueryString(url + "?" + WebUtil.BuildQueryString(queryStringDictionary, false), new[] { FieldName, FieldValue }); }
AppendFacetURL is called by the following code that controls the presentation of the refinements:
{ //<div id="relatedItems"> output.AddAttribute(HtmlTextWriterAttribute.Class, "facet"); output.RenderBeginTag(HtmlTextWriterTag.Div); //<a href='/item.aspx' output.AddAttribute(HtmlTextWriterAttribute.Href, AppendFacetUrl()); output.RenderBeginTag(HtmlTextWriterTag.A); output.Write(Name); //</a> output.RenderEndTag(); //</div> output.RenderEndTag(); }
| Search Results control with facetted list control |
Search Results.cs
The Search Results Web control uses the same classes as RelatedItems.cs to display related items and other refinements in the side bar. See the full solution source code to find out how this control has been adapted to display the same related items and facetted list in the side bar.
| Search Results control with related items control |
Next step: Testing the Solution