using System; using System.Collections.Generic; using System.Linq; using CMS.CMSHelper; using CMS.Ecommerce; using CMS.FormControls; using CMS.GlobalHelper; using CMS.ExtendedControls; public partial class CMSModules_Ecommerce_Controls_UI_PriceSelector : FormEngineUserControl { #region "Properties" /// /// Gets or sets the enabled state of the control. /// public override bool Enabled { get { return base.Enabled; } set { base.Enabled = value; txtPrice.Enabled = value; } } /// /// Gets or sets the price value. /// When set, the price value is formatted according to the specified currency. /// public override object Value { get { if (string.IsNullOrEmpty(txtPrice.Text)) { return null; } return ValidationHelper.GetDouble(txtPrice.Text, 0); } set { if (ValidationHelper.IsDouble(value)) { txtPrice.Text = GetFormattedPrice(ValidationHelper.GetDouble(value, 0)); } else { txtPrice.Text = null; } } } /// /// Gets or sets the price value. /// When set, the price value is formatted according to the specified currency. /// public double Price { get { return ValidationHelper.GetDouble(Value, 0); } set { Value = value; } } /// /// Gets a value that indicates if price is being edited for product option. /// public bool IsProductOption { get { // Try to get the value from SKU form data if ((Form != null) && Form.Data.ContainsColumn("SKUOptionCategoryID")) { return ValidationHelper.GetInteger(Form.Data.GetValue("SKUOptionCategoryID"), 0) > 0; } return false; } } /// /// Gets or sets the ID of the site specifying which main currency has to be used for the price formatting. /// The default value is the current site ID. /// public int CurrencySiteID { get { if (mCurrencySiteID >= 0) { return mCurrencySiteID; } // Try to get the value from SKU form data if ((Form != null) && Form.Data.ContainsColumn("SKUSiteID")) { int siteId = ValidationHelper.GetInteger(Form.Data.GetValue("SKUSiteID"), 0); if (siteId >= 0) { return siteId; } } return CMSContext.CurrentSiteID; } set { mCurrencySiteID = value; mCurrency = null; } } private int mCurrencySiteID = -1; /// /// Gets or sets the currency used for the price formatting. /// public CurrencyInfo Currency { get { return mCurrency ?? (mCurrency = CurrencyInfoProvider.GetMainCurrency(CurrencySiteID)); } set { mCurrency = value; mCurrencySiteID = value != null ? mCurrency.CurrencySiteID : -1; } } private CurrencyInfo mCurrency = null; /// /// Gets or sets the value that indicates if validation errors are to be shown inline by the control itself. /// public bool ShowErrors { get { return plcMessages.Visible; } set { plcMessages.Visible = value; } } /// /// Gets or sets the value that indicates whether the validation messages should be displayed under the textbox or not. /// The default value is false. /// public bool ValidatorOnNewLine { get { return ValidationHelper.GetBoolean(GetValue("ShowErrorsOnNewLine"), mMessagesOnNewLine); } set { SetValue("ShowErrorsOnNewLine", value); mMessagesOnNewLine = value; if (value) { pnlNewLineWrapper.Controls.Add(plcMessages); } else { Controls.Add(plcMessages); } } } private bool mMessagesOnNewLine = false; /// /// Gets or sets the message which is displayed by the required field validator of the price textbox. /// public string EmptyErrorMessage { get { return ValidationHelper.GetString(GetValue("EmptyErrorMessage"), null); } set { SetValue("EmptyErrorMessage", value); } } /// /// Gets or sets the message which is displayed by the range field validator of the price textbox. /// public string ValidationErrorMessage { get { return ValidationHelper.GetString(GetValue("RangeErrorMessage"), null); } set { SetValue("RangeErrorMessage", value); } } /// /// Indicates if the currency code is displayed next to the price textbox. /// The default value is true. /// public bool ShowCurrencyCode { get { return ValidationHelper.GetBoolean(GetValue("ShowCurrencyCode"), lblCurrencyCode.Visible); } set { SetValue("ShowCurrencyCode", lblCurrencyCode.Visible); lblCurrencyCode.Visible = value; } } /// /// Indicates if zero price is considered to be a valid value. /// The default value is true. /// public bool AllowZero { get { bool allowZero = ValidationHelper.GetBoolean(ViewState["AllowZero"], true); return ValidationHelper.GetBoolean(GetValue("AllowZero"), allowZero); } set { SetValue("AllowZero", value); ViewState["AllowZero"] = value; } } /// /// Indicates if zero price is considered to be a valid value. /// The default value is false. /// public bool AllowNegative { get { bool allowNegative = ValidationHelper.GetBoolean(ViewState["AllowNegative"], false); return ValidationHelper.GetBoolean(GetValue("AllowNegative"), allowNegative); } set { SetValue("AllowNegative", value); ViewState["AllowNegative"] = value; } } /// /// Indicates if empty price is considered to be a valid value. /// The default value is false. /// public bool AllowEmpty { get { return ValidationHelper.GetBoolean(GetValue("AllowEmpty"), mAllowEmpty); } set { SetValue("AllowEmpty", value); mAllowEmpty = value; } } private bool mAllowEmpty = false; /// /// Indicates if value is formatted as integer in case it is a whole number. /// The default is false. /// public bool FormatValueAsInteger { get { return ValidationHelper.GetBoolean(GetValue("FormatValueAsInteger"), mFormatValueAsInteger); } set { SetValue("FormatValueAsInteger", value); mFormatValueAsInteger = value; } } private bool mFormatValueAsInteger = false; /// /// Gets the messages placeholder. /// public override MessagesPlaceHolder MessagesPlaceHolder { get { return plcMessages; } } #endregion #region "Lifecycle methods" protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); lblCurrencyCode.Text = Currency != null ? string.Format(" ({0})", HTMLHelper.HTMLEncode(Currency.CurrencyCode)) : null; pnlNewLineWrapper.Visible = pnlNewLineWrapper.Controls.Count > 0; } #endregion #region "Validation methods" /// /// Returns true if the price value is valid, otherwise returns false. /// public override bool IsValid() { ErrorMessage = Validate(IsProductOption); return string.IsNullOrEmpty(ErrorMessage); } /// /// Validates the price value and returns an error message if the price value is invalid, otherwise returns an empty string. /// public string Validate(bool isProductOption) { List errors = ValidateInternal(isProductOption).ToList(); bool isValid = errors.Count == 0; if (!isValid) { ErrorMessage = errors.First(); ShowError(ErrorMessage); return ErrorMessage; } return string.Empty; } private IEnumerable ValidateInternal(bool isProductOption) { string price = txtPrice.Text.Trim(); // Validate empty value if (string.IsNullOrEmpty(price)) { if (AllowEmpty) { yield break; } else { yield return GetString(EmptyErrorMessage); } } if (isProductOption) { // The price value can be negative for a product option if (!ValidationHelper.IsDouble(price)) { yield return GetString(ValidationErrorMessage); } } else { // The price value cannot be negative for a basic product if (ValidationHelper.GetDouble(price, -1) < 0) { yield return GetString(ValidationErrorMessage); } } // Validate zero value if (!AllowZero && ValidationHelper.GetDouble(price, 0) == 0) { yield return GetString(ValidationErrorMessage); } } #endregion #region "Helper methods" /// /// Returns the formatted price value with the number of digits according to the currency significant digits settings. /// Formats the price value as an integer if enabled and if the price value is a whole number. /// /// The price value to be formatted private string GetFormattedPrice(double value) { // Format the price value as an integer if (FormatValueAsInteger) { double truncatedValue = Math.Truncate(value); if (value == truncatedValue) { return truncatedValue.ToString("0"); } } // Format the price value according to the currency if (Currency != null) { int digits = Currency.CurrencyRoundTo; string format = "0." + new string('0', digits); return value.ToString(format); } return value.ToString(); } #endregion }