This article demonstrates how to create a custom web control to display prices. As an example, a web control is written to show product prices in two different currencies. The example can be used as a starting point of writing your own price web control.
Important:
The web control which display prices should not be "inconsistent" with how the "Buy button" web control is behaving. The Buy Button web control puts an item to the shopping cart, and the price for the item is automatically determined based on the IPriceCalculator methods that fetches the list price. The price shown to the user from the list price webcontrol should be the price user sees when he looks at his cart.
Same rule applies for the campaign price. The campaign price of an article is determined by the campaign engine, and webcontrol that shows the campaign price should simply use it. If you show a different campaign price, that is if the campaign price shown is inconsistent with the campaign price given by the campaign engine, the end customers will be confused.
Step 1: Webcontrols assembly
Create an assembly to hold the web control. For this example we have named it as Litium.Studio.KC.Samples.WebControls which is a normal C# class library project. Note that the .net version should be same as your website projects .net version.
You might need the references shown below, (the Litium Studio assmebly files are in the wwwroot\bin directory).

Create the MultiCurrencyArticleListPrice class and extend the System.Web.UI.Control class. In this class WebControlState object is initialized as follows:
/// <summary>
/// WebControlState gives access to litium studio entity instances in current session.
/// </summary>
private WebControlState WebControlState { get; set; }
public MultiCurrencyArticleListPrice()
{
WebControlState = new WebControlState(this);
}
The price is fetched from the IPriceCalculator implementation, its concrete implementation is fetched using IoC.
Following is the complete source.
using System;
using System.ComponentModel;
using System.Web.UI;
using Litium.Foundation;
using Litium.Foundation.Currencies;
using Litium.Foundation.Languages;
using Litium.Foundation.Modules;
using Litium.Foundation.Modules.ProductCatalog.Articles;
using Litium.Foundation.Modules.ProductCatalog.Plugins.PriceCalculator;
using Litium.Foundation.Modules.ProductCatalog.Products;
using Litium.Foundation.Modules.WebControls;
using Litium.Foundation.Security;
namespace Litium.Studio.KC.Samples.WebControls
{
/// <summary>
/// This web control display the list price of an article in two currencies.
/// One currency is the default website currency,
/// the other currency is specified through the AlternativeCurrency property.
/// </summary>
public class MultiCurrencyArticleListPrice : Control
{
/// <summary>
/// WebControlState gives access to litium studio entity instances in current session.
/// </summary>
private WebControlState WebControlState { get; set; }
public MultiCurrencyArticleListPrice()
{
WebControlState = new WebControlState(this);
}
/// <summary>
/// Alternative currency to display the article price.
/// </summary>
public string AlternativeCurrency
{
//ViewState.GetValue<T> extension method is defined in Litium.Foundation namespace, in Litium.Foundation.GUI assembly.
get { return ViewState.GetValue<string>("SourceIdentifier", null); }
set { ViewState["SourceIdentifier"] = value; }
}
/// <summary>
/// Display currency symbol or not.
/// </summary>
[DefaultValue(true)]
public bool DisplayCurrencySymbol
{
get { return ViewState.GetValue("DisplayCurrencySymbol", true); }
set { ViewState["DisplayCurrencySymbol"] = value; }
}
/// <summary>
/// Gets or sets the it the price should be with our without VAT.
/// </summary>
/// <value> The setting. </value>
[DefaultValue(VATSetting.Auto)]
public VATSetting VATSetting
{
get { return ViewState.GetValue("VATSetting", VATSetting.Auto); }
set { ViewState["VATSetting"] = value; }
}
/// <summary>
/// Css class to format the current currency div.
/// </summary>
public string CssClassCurrentCurrency
{
get { return ViewState.GetValue("CssClassCurrentCurrency", ""); }
set { ViewState["CssClassCurrentCurrency"] = value; }
}
/// <summary>
/// Css class to format the alternative currency div.
/// </summary>
public string CssClassAlternativeCurrency
{
get { return ViewState.GetValue("CssClassAlternativeCurrency", ""); }
set { ViewState["CssClassAlternativeCurrency"] = value; }
}
/// <summary>
/// Renders the contents of the control to the specified writer. This method is used primarily by control developers.
/// </summary>
/// <param name="writer"> A <see cref="T:System.Web.UI.HtmlTextWriter" /> that represents the output stream to render HTML content on the client. </param>
public override void RenderControl(HtmlTextWriter writer)
{
if (DesignMode)
{
return;
}
var product = WebControlState.ProductCatalog.CurrentProduct;
if (product == null || !product.IsPublished)
{
Visible = false;
return;
}
var article = WebControlState.ProductCatalog.CurrentArticle;
var token = WebControlState.FoundationContext.Token;
var language = WebControlState.ProductCatalog.CurrentProductCatalogLanguage;
var websiteId = WebControlState.CMS.CurrentPage.WebSiteID;
var currentCurrency = WebControlState.CMS.CurrentCurrency;
var alternativeCurrency = Solution.Instance.Currencies.Get(AlternativeCurrency);
var culture = WebControlState.CMS.CurrentState.WebSite.Culture;
var includeVat = VATSetting == VATSetting.Auto ?
WebControlState.CMS.CurrentState.ShoppingCart.IncludeVAT :
(VATSetting == VATSetting.Include ? true : false);
//render price in normal website currency.
var listPriceCurrentCurrency = GetListPrice(currentCurrency, product, article, language, websiteId, token);
if (listPriceCurrentCurrency != null)
{
var price = includeVat ? listPriceCurrentCurrency.ListPriceWithVAT : listPriceCurrentCurrency.ListPrice;
var output = string.Format("<div class=\"{0}\">{1}</div>", CssClassCurrentCurrency, currentCurrency.Format(price, DisplayCurrencySymbol, culture));
writer.Write(output);
}
//render alternative price
var listPriceAlternativeCurrency = GetListPrice(alternativeCurrency, product, article, language, websiteId, token);
if (listPriceAlternativeCurrency != null)
{
var price = includeVat ? listPriceAlternativeCurrency.ListPriceWithVAT : listPriceAlternativeCurrency.ListPrice;
var output = string.Format("<div class=\"{0}\">{1}</div>", CssClassAlternativeCurrency, alternativeCurrency.Format(price, DisplayCurrencySymbol, culture));
writer.Write(output);
}
}
/// <summary>
/// Gets the price for given product.
/// </summary>
/// <param name="currency">The currency.</param>
/// <param name="product">The product.</param>
/// <param name="article">The article.</param>
/// <param name="language">The language.</param>
/// <param name="websiteId">The website id.</param>
/// <param name="token">The token.</param>
/// <returns></returns>
private static ListPriceResult GetListPrice(Currency currency,
Product product, Article article, Language language, Guid websiteId, SecurityToken token)
{
//validate.
if (currency == null || product == null || article == null || language == null || websiteId==Guid.Empty)
return null;
ListPriceResult listPrice = null;
// get price from price calculator.
var priceCalculatorArgs = new PriceCalculatorArgs
{
ArticleID = article.ID,
AssortmentID = product.AssortmentID,
CurrencyID = currency.ID,
Date = DateTime.Now,
LanguageID = language.ID,
ProductID = product.ID,
Quantity = 1,
SecurityToken = token,
SourceIdentifier = string.Empty, //this parameter should be sent in if price calculator is overriden and uses this value.
UserID = token.UserID,
WebSiteID = websiteId
};
var priceCalculator = IoC.Resolve<IPriceCalculator>();
priceCalculator.GetListPrices(priceCalculatorArgs).TryGetValue(priceCalculatorArgs.ArticleID, out listPrice);
return listPrice;
}
}
}
To use the webcontrol, this project should be added as a reference to the web project (or the dll file generated should be manually coppied to the wwwroot\bin directory.
In the web.config file, add the tag prefix to pages>xontrols section so that webcontrols from this assembly can be used in any aspx page.
<add tagPrefix="kcSamples" namespace="Litium.Studio.KC.Samples.WebControls" assembly="Litium.Studio.KC.Samples.WebControls"/>
Following code fragment demostrate how we can use the web control in a aspx file. We have taken a product repeater as an example, however any control that implements IProductIntroducer interface can be the parent of this webcontrol.
<pc:ProductRepeater ID="ProductRepeater" runat="server">
<HeaderTemplate>
<ul class="products container">
</HeaderTemplate>
<ItemTemplate>
<li class="grid_2">
<div class="imageholder">
<PC:DisplayImageExists runat="server">
<OnTrue>
<pc:ProductLink runat="server">
<pc:DisplayImage MaxHeight="130" MaxWidth="140" runat="server" />
</pc:ProductLink>
</OnTrue>
</PC:DisplayImageExists>
</div>
<h2>
<pc:ProductLink runat="server">
<pc:DisplayName runat="server" />
</pc:ProductLink>
</h2>
<PC:IsArticle runat="server">
<OnTrue>
<div class="buyarea">
<kcSamples:MultiCurrencyArticleListPrice AlternativeCurrency="USD" DisplayCurrencySymbol="true" runat="server" />
</div>
</OnTrue>
</PC:IsArticle>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</pc:ProductRepeater>
The final output would look similar to:
