Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Margin Calculator Control

0.00/5 (No votes)
10 Sep 2010 1  
.NET 4.0 WPF control that allows you to enter a cost and sale price and compute a margin.

Introduction

This is a WPF user control that I recently created for a project I'm working on.

It's pretty basic, you enter a cost and optionally a sale price and it will tell you what price to sell the item for and what margin you will make on it, as well as profit.

The UI for the control is made up of some basic WPF controls and includes some simple gradient backgrounds.

There is also a cool glass button, that is located in the UserControl.Resources section.
You can take the control template for the Glass Button and customize it to fit your needs.

I have included a demo application with the code download, as well as a screenshot below.

MarginCalculator.png

Using the Code

To use this control, just right-click the toolbox in Visual Studio and add a reference to the
CodeLogix.Controls.MarginCalculator namespace.

This will add the control to the toolbox and allow you to drag and drop it on your WPF design surface.

NOTE: I have also included a simple numeric only textbox for WPF in the download.

This will allow you to input only numbers and the decimal separator into the Cost and Sale Price fields.

The code for it is pretty simple, we just sub-class the System.Windows.Controls.TextBox class and override the OnPreviewTextInput method. Then we need to create a helper method to verify valid input.

Numeric Only TextBox Code

   protected override void OnPreviewTextInput
	(System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !AreAllValidNumericChars(e.Text);
        base.OnPreviewTextInput(e); 
    }
    
    static bool AreAllValidNumericChars(string str)
    {
        bool ret = true;
        if (str == System.Globalization.NumberFormatInfo.CurrentInfo.
		CurrencyDecimalSeparator |                
            str == System.Globalization.NumberFormatInfo.
		CurrentInfo.NumberDecimalSeparator)
            
            return ret;
            
        int l = str.Length;
        for (int i = 0; i < l; i++)
        {
            char ch = str[i];
            ret &= Char.IsDigit(ch);
        }
        
        return ret;
    }
}

Margin Calculator Code

public partial class MarginCalculator : UserControl
{       
    public MarginCalculator()
    {
        InitializeComponent();
    }
    
    // This is used to store the values for the different margin textBlock controls.
    internal struct MarginValues
    {           
        public double TwentyFivePercent { get; set; }
        public double ThirtyPercent { get; set; }
        public double ThirtyFivePercent { get; set; }
        public double FortyPercent { get; set; }
        public double FortyFivePercent { get; set; }
        public double FiftyPercent { get; set; }
        public double FiftyFivePercent { get; set; }
        public double SixtyPercent { get; set; }
        public double SixtyFivePercent { get; set; }
    }
    
    // Here we calculate the profit margin, by subtracting the sale price, 
    // minus the cost, divided by the sale price. 
    
    private static double CalculateProfitMargin(double cost, double salePrice)
    {
        return (salePrice - cost) / salePrice;
    }
    
    private static MarginValues CalculateMargin(double costOfPart)
    {
        MarginValues values = new MarginValues 
        { 
            TwentyFivePercent = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.73))), 
            ThirtyPercent     = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.68))), 
            ThirtyFivePercent = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.63))), 
            FortyPercent      = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.58))), 
            FortyFivePercent  = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.53))), 
            FiftyPercent      = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.49))), 
            FiftyFivePercent  = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.44))), 
            SixtyPercent      = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.39))), 
            SixtyFivePercent  = Math.Round(((1 - Convert.ToDouble(costOfPart)) / (-0.34))) 
        };
        return values;
    }
    
    // Here we check for valid input and compute the results. 
    private void RunCalculations()
    {
        MarginValues results = new MarginValues();
        if (!String.IsNullOrEmpty(textBoxCostOfPart.Text))
        {
            double cost;
            if (double.TryParse(textBoxCostOfPart.Text, out cost))
            {
                results = CalculateMargin(cost);
                if (!String.IsNullOrEmpty(textBoxSalePrice.Text))
                {
                    double salePrice;
                    if (double.TryParse(textBoxSalePrice.Text, out salePrice))
                    {
                        double profitMargin = CalculateProfitMargin(cost, salePrice);
                        margin.Text = profitMargin.ToString("p");
                        double profit = salePrice - cost;
                        this.profit.Text = profit.ToString("c");
                    }
                }
            }
        }
        // set the percent textblocks
        twentyFivePercent.Text = results.TwentyFivePercent.ToString("c");
        thirtyPercent.Text     = results.ThirtyPercent.ToString("c");
        thirtyFivePercent.Text = results.ThirtyFivePercent.ToString("c");
        fortyPercent.Text      = results.FortyPercent.ToString("c");
        fortyFivePercent.Text  = results.FortyFivePercent.ToString("c");
        fiftyPercent.Text      = results.FiftyPercent.ToString("c");
        fiftyFivePercent.Text  = results.FiftyFivePercent.ToString("c");
        sixtyPercent.Text      = results.SixtyPercent.ToString("c");
        sixtyFivePercent.Text  = results.SixtyFivePercent.ToString("c");
    }
    
     // The rest of the code simply invokes the calculation code,
    // whenever a user clicks the GO button, or types valid input into the
    // Cost or Sale Price textBox.
    private void buttonCalculate_Click(object sender, RoutedEventArgs e)
    {
       RunCalculations();
    }
     
    private void textBoxCostOfPart_KeyDown(object sender, KeyEventArgs e)
    {
        RunCalculations();
    }
    
    private void textBoxSalePrice_KeyDown(object sender, KeyEventArgs e)
    {
        RunCalculations();
    }
    
    private void textBoxCostOfPart_GotFocus(object sender, RoutedEventArgs e)
    {
        textBoxCostOfPart.SelectAll();
    }
    
    private void textBoxSalePrice_GotFocus(object sender, RoutedEventArgs e)
    {
        textBoxSalePrice.SelectAll();
    }
    
    private void textBoxSalePrice_GotMouseCapture(object sender, MouseEventArgs e)
    {
        textBoxSalePrice.SelectAll();
    }
    
    private void textBoxCostOfPart_GotMouseCapture(object sender, MouseEventArgs e)
    {
        textBoxCostOfPart.SelectAll();
    }
}

If anyone finds this control useful and/or has any way to improve it, please leave a comment and let me know.

Points of Interest (ToolBox Icon)

One thing I did was to add a custom icon for my control to the ToolBox in Visual Studio. If anyone is unsure how to do this, let me explain.

  1. First you need to add an image at the same level in your project, as your user control.
  2. Then make sure you rename the image to be UserControlName.Icon.YourImageExtension.
  3. Next, make sure you set the image to be an embedded resource in the properties window.

NOTE: Your custom icon will not show up in the automatically added toolbox items for your user control.

You will need to Right-Click and Add Item, then browse to your User Control's assembly and add it to the toolbox.

Then everything will work as expected.

History

  • 9/2/2010: Uploaded first version of Control

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here