Cannot add together different variables, even though values have changed - c#

So I'm REALLY new to coding, so I'm learning as I go. I'm doing an assignment for a course, where I have to create a party booking program for a company. The idea is simple, just selected some different options, add them up, and calculate the costs. I have labels that will change and display the integer that the variable is set to, and they work perfectly which would tell me that the variables themselves are indeed getting changed.
However, once I try to add the variables together, it doesn't work.
public partial class AdultPayment : Form
{
public static int ConvertNumberAdult = Convert.ToInt32(Adult.numberAdult);
public static int MealCost = Adult.mealPrice*ConvertNumberAdult;
private static int PrivateRoomCost;
public static int TotalCost = MealCost + CalculateWine + PrivateRoomCost;
public static string DisplayNumberAdult = Convert.ToString(Adult.numberAdult);
private static int CalculateWine { get; set; } = ConvertNumberAdult / 6 * 15;
public AdultPayment()
{
InitializeComponent();
lblAdultConfirmName.Text = Adult.adultContactName;
lblAdultConfirmNumber.Text = Adult.adultContactNumber;
lblAdultConfirmDate.Text = Adult.adultDate;
lblAdultConfirmTime.Text = Adult.adultTime;
lblConfirmNumberOfAdult.Text = Adult.numberAdult.ToString();
lblMealCostTotal.Text = "£"+ MealCost.ToString();
lblCostTotal.Text = "£" + TotalCost.ToString();
if (Adult.adultPrivateRoom == true)
{
PrivateRoomCost = 40;
lblAdultConfirmPrivateRoom.Text = "Yes";
lblPrivateRoomTotal.Text = "£"+ PrivateRoomCost;
}
else
{
PrivateRoomCost = 0;
lblAdultConfirmPrivateRoom.Text = "No";
lblPrivateRoomTotal.Text = "N/A";
}
if(Adult.menuOption == true)
{
lblConfirmMenu.Text = "2 Courses for £15 each";
}
if(Adult.menuOption == false)
{
lblConfirmMenu.Text = "3 Courses for £18 each";
}
if (Adult.addWine == false)
{
CalculateWine = 0;
lblConfirmWineAdded.Text = "No";
lblWineTotal.Text = "N/A";
}
else
{
lblConfirmWineAdded.Text = "Yes";
lblWineTotal.Text = "£"+ CalculateWine.ToString();
}
lblCostTotal.Text = "£" + TotalCost.ToString();
}
}
I have a different form, that allows the users to select their preferences, which works just as I need it to.
The variable that is supposed to add the other variables together is
public static int TotalCost = MealCost + CalculateWine + PrivateRoomCost;
I genuinely am so confused now, and because I'm so new to this I don't know how else to word it in order to find anything on the internet
Any help would be great!
Thanks!

Related

Rewriting my code as a Method, using C# Visual Studio

I am currently having trouble understanding Methods and how they work in C#. I currently have code written for a car cost calculator program I created, I want to rearrange or break my code down using methods. I am unsure how or where to begin doing so as it pertains to my program. Here is my code, clarification would be helpful! Thank you!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//constants for the Zone entered by user
const decimal ZoneCostN = 27;
const decimal ZoneCostS = 36;
const decimal ZoneCostE = 45;
const decimal ZoneCostW = 54;
private void CalcButton_Click(object sender, EventArgs e)
{
//set the variables
decimal PackWeight = 0;
decimal CostZone = 0;
decimal CostWeight = 0;
decimal ShippingTot = 0;
decimal Net = 0;
const decimal PerPound = 18;
//parses the entry into the textboxes
decimal.TryParse(WeightText.Text, out PackWeight); ;
//algorithm for variables
CostWeight = PackWeight * PerPound;
Zonelbl.Text = "";
CostZone = 0;
//if else statement to get the zone cost
{
if (NorthButton.Checked)
{
CostZone = ZoneCostN;
}
else if (SouthButton.Checked)
{
CostZone = ZoneCostS;
}
else if (EastButton.Checked)
{
CostZone = ZoneCostE;
}
else if (WestButton.Checked)
{
CostZone = ZoneCostW;
}
else
{
MessageBox.Show("Select a zone!");
}
}
//algorithm to get total and net
ShippingTot = CostZone + CostWeight;
Net = ShippingTot / CostWeight;
//if condition for CAPPED label
if (ShippingTot >= 100)
{
CAPPEDlbl.Visible = true;
}
else
{
CAPPEDlbl.Visible = false;
}
//output for all the data
Zonelbl.Text = CostZone.ToString("c");
Weightlbl.Text = CostWeight.ToString("c");
Totallbl.Text = ShippingTot.ToString("c");
Netlbl.Text = Net.ToString("c");
}
private void ClearButton_Click(object sender, EventArgs e)
{
//clears the form
Zonelbl.Text = "";
Weightlbl.Text = "";
Totallbl.Text = "";
Netlbl.Text = "";
WeightText.Text = "";
CAPPEDlbl.Visible = false;
WeightText.Focus();
}
}
Usually, we create methods when we need to reuse a code. In your case, you should see which part of your code will be reused in the future. If it is a simple form you may don't need to change anything but imagine you want to use your clear functionality somewhere else, create a method and call it everywhere you need
void clear()
{
Zonelbl.Text = "";
Weightlbl.Text = "";
Totallbl.Text = "";
Netlbl.Text = "";
WeightText.Text = "";
CAPPEDlbl.Visible = false;
WeightText.Focus();
}
private void ClearButton_Click(object sender, EventArgs e)
{
clear();
}
Now you can reuse clear() and in case you needed to change it you only need to change the method. It's the concept and you can apply it wherever you need.

How could I refactor this method in C#?

I have code which I need to refactor in order to use in many places. So I tried some solutions but always ending with repeated and messy code. So, I decided to ask what is possible best solutions.
This code is used for calculating sale price in e-commerce project. My goal is to put some code in method which will not change over time, or better to say, which will be managed only from one place. This part is considering of setting sale price based on some comparasion.
And problem occurs in this comparasion. I want also to do some formating of controls like Label based on this result, like setting currency code. The currency code will be sometimes in $, sometimes in USD. So, this mean I should somehow isolete this currency code also.
In short, I want to refactor this currency code and formating controls based on calculated sale price.
So, I created BasketHelper class with Product and Account properties and method SetBasketPayment that return properties I setted in this method. Basically, I use this approach to group properties of Product and Account classes and than return values.
Here is my code. Any further explanation, I will provide upon your request.
public class BasketHelper
{
public Product _product { get; set; }
public Account _account { get; set; }
public BasketHelper SetBasketPayment(Product product, Account account, HyperLink lblIconOnSale, Label lblSalePrice, Label lblListPrice, HyperLink lblIconCampaign)
{
decimal _brandAccountDiscountRate = default(decimal);
decimal _accountDiscount = default(decimal);
if (HttpContext.Current.Request.IsAuthenticated)
{
MembershipUser mUser = Membership.GetUser();
if (mUser != null)
{
account = Account.GetAccountByUserId((Guid)Membership.GetUser().ProviderUserKey);
try
{
_accountDiscount = account.DiscountRate;
}
catch (Exception ex) { }
BrandAccountDiscount brandAccountDiscount = BrandAccountDiscount.GetBrandAccountDiscountByUserAndBrandId(product.BrandId, mUser.ProviderUserKey.ToString());
if (brandAccountDiscount != null)
{
_brandAccountDiscountRate = brandAccountDiscount.DiscountRate;
}
}
}
decimal currencyMultiplier = Currency.GetCurrencyValue(product.CurrencyCode);
decimal _listPriceTL = product.ListPrice * currencyMultiplier;
decimal _productCampaignPrice = _listPriceTL * (1 - product.DiscountRate / 100);
decimal _accountPrice = _listPriceTL * (1 - _accountDiscount / 100);
decimal _brandPrice = _accountPrice * (1 - _brandAccountDiscountRate / 100);
lblListPrice.Text = product.ListPrice.ToString("N2") + " " + product.CurrencyCode;
if (product.DiscountRate > 0)
{
product.SalePrice = _productCampaignPrice;
lblSalePrice.Text = _productCampaignPrice.ToString("C2") + " + KDV";
lblListPrice.CssClass += " strike";
lblIconCampaign.Text = "+%" + product.DiscountRate.ToString("N0");
lblIconCampaign.Visible = true;
}
else
{
if (_accountPrice < _listPriceTL)
{
product.SalePrice = _accountPrice;
lblIconOnSale.Text = "%" + _accountDiscount.ToString();
lblIconOnSale.Visible = true;
}
if (_brandAccountDiscountRate > 0)
{
product.SalePrice = _brandPrice;
lblSalePrice.Text = _brandPrice.ToString("C2") + " +KDV";
}
}
return new BasketHelper
{
_product = product,
_account = account
};
}
}

Align in RichtextBox

Using this:
richTextBox1.AppendText("EMPID: " + "\t\t" + "4001");
richTextBox1.AppendText(System.Environment.NewLine);
richTextBox1.AppendText(System.Environment.NewLine);
richTextBox1.AppendText("EmployeeName: " + "\t\t" + "Taborjakol");
I got this:
How I will perfectly Align it to this:
What you can do is change the tab positions of the RichTextBoxControl.
richTextBox1.SelectionTabs = new int[] { 90, 180, 270, 360 };
richTextBox1.AppendText("EMPID: " + "\t\t" + "4001");
richTextBox1.AppendText(System.Environment.NewLine);
richTextBox1.AppendText(System.Environment.NewLine);
richTextBox1.AppendText("EmployeeName: " + "\t\t" + "Taborjakol");
The SelectionsTab property re-defines the spaces that are used for each tab in the RichTextBox control. You need to experiment with the tab settings to get the best result for your text.
Replace your last line of code with
richTextBox1.AppendText("EmployeeName: " + "\t" + "Taborjakol");
If you dont have to use a richtextbox, you should definetly have a look at the gridview or if you use third party tools like Telerik, DevCraft, ComponentOne and others most of them will have a control called Property Grid that has a layout you might be interested in.
If there is no other way around in using a richtextbox, you have to do the following:
Get a fixed-width font or called monospaced font http://en.wikipedia.org/wiki/Monospaced_font
Evalute the amout of characters which share the same width as a tab (I dont know the number of character have to figure it out yourself with testing)
Get the max length of your text at the left side (your "columnnames" I guess - like "EmployeeName")
Do some math - max length + one tab = x characters
now fill the remaining text at your left side with the neccessary tabs (can be anything from 1 to x) to get the same amout of characters as calculated in 4.
But again a richtextbox isnt the ideal control for this kind of scenario.
Edit:
Here some Code:
public partial class Form1 : Form
{
private const int FetchTestData = 50;
private const int TabCharLength = 5;
public Form1()
{
InitializeComponent();
//With this Fontsettings - 5 chars = 1 Tab - this changes with different fonts
this.richTextBox1.Font = new System.Drawing.Font("Courier New", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
var type = typeof(TestData);
var list = GetTestData();
var maxProperty = GetMaxProperty(type);
maxProperty = FillToNext(maxProperty);
var properties = GetProperties(type);
for (var i = 0; i < FetchTestData; i++)
{
var data = list[i];
foreach (var propertyInfo in properties)
{
richTextBox1.AppendText(propertyInfo.Name);
var tabs = GetNumberOfTabs(maxProperty, propertyInfo.Name.Length);
for (var j = 0; j < tabs; j++)
richTextBox1.AppendText("\t");
richTextBox1.AppendText(Convert.ToString(propertyInfo.GetValue(data)));
richTextBox1.AppendText(Environment.NewLine);
}
if (i >= FetchTestData - 1)
continue;
richTextBox1.AppendText(Environment.NewLine);
richTextBox1.AppendText("---------- NEXT DATA ----------");
richTextBox1.AppendText(Environment.NewLine);
}
}
private int GetNumberOfTabs(int maxLength, int textLength)
{
if ((maxLength % TabCharLength) != 0)
maxLength = FillToNext(maxLength);
var difLength = maxLength - textLength;
return (int)(Math.Floor(Convert.ToDouble(difLength / TabCharLength)) + 1);
}
private int FillToNext(int maxLength)
{
return maxLength + (5 - (maxLength % TabCharLength));
}
private PropertyInfo[] GetProperties(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
return type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
}
private int GetMaxProperty(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
return (from x in GetProperties(type)
select x.Name.Length).Max();
}
private List<TestData> GetTestData()
{
var returnValue = new List<TestData>();
for (int i = 0; i < FetchTestData; i++)
{
returnValue.Add(new TestData()
{
ID = i,
Name = "NameValue " + i,
Description = "DescriptionValue " + i,
PropertyA = "PropertyAValue " + i,
PropertyB = "PropertyBValue " + i,
SomeReallyLongPropertyName = "RandomStuff... " + i
});
}
return returnValue;
}
}
public class TestData
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public string SomeReallyLongPropertyName { get; set; }
}
As stated you firstly would want to set the font to a mono-space font, this means that each letter will be the same size.
So you will see something like this:
EEEEEEEEEEE
Rather than
EeEeeiiiiiiiiiiiiiiiiii
Secondly, you could align the text which may improve it slightly:
richTextBox1.SelectAll();
richTextBox1.SelectionAlignment = HorizontalAlignment.Center;
However unless you have to, I would suggest using a different control:
Gridview
Listbox
These are both easy to format, gridview has tabs, and the listbox you can use string.Format when entering the values.

Calculate Running Total Using LINQ to SQL

I have a WPF C# Application which is accessing data through a SQL-LINQ connection and putting it on a Datagrid. I have added a Running Pips column and have been trying to figure out how in to get this column populated correctly. I have found several methods through searching the web, but none of these are appropriate for my particular setup. Most of the time I end up in an endless loop. I would like the Running Pips column to be cumulative and the order of the calculation to start from the earliest 'Close Time'.
Close Time Profit Running Profit
10.09.11 $10 $10
10.10.11 $20 $30
10.11.11 $15 $45
Here is a summary of the code. I hope someone can suggest how to fix this code with any relevant information needed to aid me in implementing this:
public void RefreshClose() {
if (CloseTradeCollection == null) return;
var i = 0;
if (StaticTool.SelectedAccount == null) {
ExistCloseTrade = false;
CloseTradeCollection.Clear();
return;
}
Account = StaticTool.SelectedAccount;
foreach (var trade in GetClosedTradesFromDb()) {
if (CloseTradeCollection.Count <= i) {
ExistCloseTrade = true;
var tradeDetails = new Trade {
Id = trade.id,
Ticket = trade.ticket,
OpenTime = trade.opentime,
CloseTime = trade.closetime,
Symbol = trade.symbol,
OpenPrice = trade.openprice,
ClosePrice = trade.closeprice,
Profit = trade.profit,
Comment = trade.comment.Trim(),
};
tradeDetails.History = tradeDetails.CloseTime - tradeDetails.OpenTime;
CloseTradeCollection.Add(tradeDetails);
}
else {
var tradeDetails = CloseTradeCollection[i];
tradeDetails.Id = trade.id;
tradeDetails.Ticket = trade.ticket;
tradeDetails.OpenTime = trade.opentime;
tradeDetails.CloseTime = trade.closetime;
tradeDetails.Symbol = trade.symbol;
tradeDetails.OpenPrice = trade.openprice;
tradeDetails.ClosePrice = trade.closeprice;
tradeDetails.Profit = trade.profit;
tradeDetails.Comment = trade.comment.Trim();
tradeDetails.History = DateTime.Now - tradeDetails.OpenTime;
//tradeDetails.RunningProfit = ????????
}
i++;
}
}
You can create a local variable to keep track of running profit, making use of the fact that the assignment operation returns the value being assigned.
tradeDetails.RunningProfit = (runningProfit = runningProfit + trade.profit);
Here is a general idea - you should be able to adopt it to your needs:
class Trade {
public DateTime CloseTime { get; set; }
public decimal Profit { get; set; }
}
class TradeWithRunningProfit : Trade {
public decimal RunningProfit { get; set; }
}
class Program {
static IEnumerable<TradeWithRunningProfit> GetRunningProfits(IEnumerable<Trade> rows) {
decimal running_profit = 0;
return
from row in rows
select new TradeWithRunningProfit {
CloseTime = row.CloseTime,
Profit = row.Profit,
RunningProfit = (running_profit += row.Profit)
};
}
static void Main(string[] args) {
var rows = new[] {
new Trade { CloseTime = new DateTime(11,10,09), Profit = 10},
new Trade { CloseTime = new DateTime(11,10,10), Profit = 20},
new Trade { CloseTime = new DateTime(11,10,11), Profit = 15},
};
foreach (var row_with_running_profit in GetRunningProfits(rows)) {
Console.WriteLine(
"{0}\t{1}\t{2}",
row_with_running_profit.CloseTime,
row_with_running_profit.Profit,
row_with_running_profit.RunningProfit
);
}
}
}

Only top row of DataGridView updating?

I have a DataGridView that I'm populating from a list. The function that edits this list is called LoadCollectionData()'. Extra rows get added to the list just fine, and the relevant data pertaining to that row populates when the row is added.
The problem is that later on when other data is being changed that'd alter what's displayed on the datagrid, only the top row continues to update, all of the others remain the same.
Here's the code for the method:
public bool haschanged = false;
public class KeywordDensity
{
public bool included { get; set; }
public string keyword { get; set; }
public string occurences { get; set; }
public string density { get; set; }
}
public int WordCount(string txtToCount)
{
string pattern = "\\w+";
Regex regex = new Regex(pattern);
int CountedWords = regex.Matches(txtToCount).Count;
return CountedWords;
}
public int KeywordCount(string txtToCount, string pattern)
{
Regex regex = new Regex(pattern);
int CountedWords = regex.Matches(txtToCount).Count;
return CountedWords;
}
public List<KeywordDensity> LoadCollectionData()
{
string thearticle = txtArticle.Text.ToLower();
string keywordslower = txtKeywords.Text.ToLower();
string[] keywordsarray = keywordslower.Split('\r');
List<KeywordDensity> lsikeywords = new List<KeywordDensity>();
bool isincluded = false;
double keywordcount = 0;
double wordcount = WordCount(thearticle);
double thedensity = 0;
foreach (string s in keywordsarray)
{
if (s != "")
{
keywordcount = KeywordCount(thearticle, s);
thedensity = keywordcount / wordcount;
thedensity = Math.Round(thedensity, 4) * 100;
if (thearticle.Contains(s))
{
isincluded = true;
}
else
{
isincluded = false;
}
lsikeywords.Add(new KeywordDensity()
{
included = isincluded,
keyword = s,
occurences = keywordcount.ToString(),
density = thedensity.ToString() + "%"
});
}
}
return lsikeywords;
}
private void txtArticle_TextChanged(object sender, EventArgs e)
{
if (haschanged == false)
haschanged = true;
lblWordCountNum.Text = WordCount(txtArticle.Text).ToString();
dataGrid.DataSource = LoadCollectionData();
}
private void dataGrid_MouseUp(object sender, MouseEventArgs e)
{
int cursorpos = 0;
string copied = "";
if (dataGrid.CurrentCellAddress.X == 1) //Only grab content if the "Keyword" column has been clicked on
copied = " " + dataGrid.CurrentCell.Value.ToString() + " ";
cursorpos = txtArticle.SelectionStart;
txtArticle.Text = txtArticle.Text.Insert(cursorpos, copied);
}
What's even more odd, is that when I click on any of the rows, then they immediately update. However, unless the row is clicked on (unless it's the top one) it doesn't update.
Because of this, I suspect there may be some property I need to set on the dataGrid itself, or I need to somehow tell each row to refresh through code.
What's the dealio?
EDIT: It appears that the only reason that the cell that's clicked on updates is because I actively grab content from the cell. I commented out the code below and it stopped updating even when clicked on. It then would only update the top row's values and that's it.
Code:
//Moved above in EDIT 3
EDIT 2: Here's the class declaration for KeywordDensity:
//Moved above in EDIT 3
EDIT 3: Posted whole schebang.
I modified the code slightly, try this code.
string[] keywordsarray = keywordslower.Split
(new char[] {'\r','\n' }, StringSplitOptions.RemoveEmptyEntries);
You may need to Invalidate() the control to trigger a repaint.
call the DataBind() method of the datagrid. That should do.
Update
There's a ResetBindings() in that case.

Categories

Resources