C# Class scope issue? - c#

I am a student. This is our first project using two different class files, and it is also only the second one using Forms. So, I don't have much experience with either.
The object is declared and instantiated, but the object is not recognized in any of the subsequent methods. I am following the code on the book. The code on the book declares/instantiates like this:
new Order = new Order( );
I think it needs to be like this, but that still doesn't help the subsequent references:
Order newOrder = new Order( );
This a a complete listing of the driver and the two class files:
Driver:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Diner
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new OrderGUI());
}
}
}
OrderGUI.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Diner
{
public partial class OrderGUI : Form
{
public OrderGUI()
{
InitializeComponent();
}
//For Load - create object
private void OrderGUI_Load(object sender, System.EventArgs e)
{
newOrder = new Order();
for (int i = 0; i < newOrder.menuEntree.Length; i++)
{
this.lstBxEntree.Items.Add(newOrder.menuEntree[i]);
}
}
// Event handler that gets the entree from the
// Listbox and sets the entree price of the Order object.
private void lstBxEntree_SelectedIndexChanged
(object sender, System.EventArgs e)
{
newOrder.Entree = this.lstBxEntree.Text;
}
// Event handler that gets the special request -
// if one is selected from the predefined list.
private void cmboSpecial_SelectedIndexChanged
(object sender, System.EventArgs e)
{
newOrder.SpecialRequest = this.cmboSpecial.Text;
}
// Menu item that displays the order.
private void menuDisplayOrder_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets the radio button selected and
// sets the drink selection for the Order object
private void Drink_CheckedChanged(object sender,
System.EventArgs e)
{
if (this.radTea.Checked)
newOrder.DrinkSelection = radTea.Text;
else
if (this.radCoffee.Checked)
newOrder.DrinkSelection = radCoffee.Text;
else
if (this.radSoda.Checked)
newOrder.DrinkSelection = radSoda.Text;
else
if (this.radLemon.Checked)
newOrder.DrinkSelection = radLemon.Text;
else
if (this.radJuice.Checked)
newOrder.DrinkSelection = radJuice.Text;
else
if (this.radMilk.Checked)
newOrder.DrinkSelection = radMilk.Text;
}
// Event handler that gets raised when the check box
// for the Water gets clicked.
private void ckBxWater_CheckedChanged
(object sender, System.EventArgs e)
{
if (this.ckBxWater.Checked)
newOrder.WaterSelection = true;
else
newOrder.WaterSelection = false;
}
// Event handler that gets raised when the user types
// values into the text area of the combo box.
private void cmboSpecial_KeyPress
(object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
newOrder.SpecialRequest = this.cmboSpecial.Text;
}
// Event handler that gets raised when the Edit menu
// is clicked to change the entree.
private void menuEditEntree_Click
(object sender, System.EventArgs e)
{
}
// Event handler that gets raised when the Edit menu
// is clicked to change the drink.
private void menuEditDrink_Click
(object sender, System.EventArgs e)
{
}
// Clears selections for all drink radio buttons.
public void ClearDrinks()
{
this.radMilk.Checked = false;
this.radJuice.Checked = false;
this.radSoda.Checked = false;
this.radLemon.Checked = false;
this.radTea.Checked = false;
this.radCoffee.Checked = false;
}
// Clears all selections so that a new order
// can be placed. Resets the Order object back
// to its default values.
private void menuClearOrder_Click
(object sender, System.EventArgs e)
{
}
// Displays the values for the current instance of
// Order object members
private void menuPlaceOrder_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets raised when the Edit menu
// is clicked to change the special requests.
private void menuEditSpecial_Click(object sender,
System.EventArgs e)
{
}
// Event handler that gets raised when the Help
// menu is clicked to show the About message.
private void menuAbout_Click(object sender,
System.EventArgs e)
{
MessageBox.Show("Student Union -" +
" Diner by the Valley" +
"\n\n\nVersion 1.0");
}
// Event handler that gets raised when the
// Exit is clicked
private void menuExit_Click(object sender,
System.EventArgs e)
{
Application.Exit();
}
}
}
Order.cs:
using System;
using System.Windows.Forms;
namespace Diner
{
public class Order
{
public string[] menuEntree = new
string[] {"Chicken Salad",
"Ham and Cheese",
"Turkey",
"Vegetable Wrap",
"Tuna Salad",
"Avocado and Cheese",
"Club",
"Peanut Butter & Jelly",
"Cheese Toasty",
"Reuben"};
public decimal[] menuEntreePrice = new
decimal[] {4.50m,
5.00m,
4.75m,
4.00m,
4.50m,
4.00m,
5.50m,
3.75m,
3.50m,
5.00m};
private string entree;
private bool waterSelection;
private string drinkSelection;
private string specialRequest;
private decimal entreePrice;
private decimal drinkPrice;
// Default Constructor
public Order()
{
entree = "";
waterSelection = false;
specialRequest = "";
drinkPrice = 0;
entreePrice = 0;
}
//Property for Entree
public string Entree
{
get
{
return entree;
}
set
{
entree = value;
SetEntreePrice();
}
}
// Property for special request
public string SpecialRequest
{
get
{
return specialRequest;
}
set
{
specialRequest = value;
}
}
// Property for Water Selection
public bool WaterSelection
{
set
{
waterSelection = value;
}
}
// Property for Drink Selection
public string DrinkSelection
{
get
{
return drinkSelection;
}
set
{
drinkSelection = value;
SetDrinkPrice();
}
}
// Read-only property for entreee price
public decimal EntreePrice
{
get
{
return entreePrice;
}
}
// Read-only property for drink price
public decimal DrinkPrice
{
get
{
return drinkPrice;
}
}
// After the entree is set, store the entree price
public void SetEntreePrice()
{
for (int i = 0; i < menuEntree.Length; i++)
{
if (menuEntree[i] == entree)
{
entreePrice = menuEntreePrice[i];
}
}
}
// Return the water selection
public string GetWaterSelection()
{
string waterOrNot;
if (waterSelection)
{
waterOrNot = "Water";
}
else
{
waterOrNot = "No Water";
}
return waterOrNot;
}
// After the drink is set, store the drink price
public void SetDrinkPrice()
{
switch (drinkSelection)
{
case "Tea":
case "Coffee":
drinkPrice = 1.50m;
break;
case "Soda":
case "Lemonade":
drinkPrice = 2.00m;
break;
case "Milk":
case "Juice":
drinkPrice = 1.75m;
break;
}
}
// return the total cost of the order
public decimal DetermineTotalCharges()
{
return entreePrice + drinkPrice;
}
public override string ToString()
{
return "Toatal Due: " + DetermineTotalCharges().ToString("C");
}
}
}

Related

Event Handler Fires Twice When Plugging/Unplugging USB Serial Port

I am writing a program which is supposed to detect when a USB serial device is plugged in and then log on to the new com port. The code below works wonderfully, but I have noticed in debugging the code and stepping through it that the event handler "DetectChange" fires twice. I'm not sure that this is normal, or an action of the debugger.
In any case, the code works, but I am new at event handling and I would like to make sure that I am not going to cause any issues as I add more code to actually read and write from the serial port.
(I got some of this code from stackoverflow, but I have misplaced my paper with names for attribution. If you see your code below, my heartfelt thanks.)
using System;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management;
using System.Threading;
namespace SerialTest
{
public partial class Form1 : Form
{
SerialMethods serialMethods = new SerialMethods();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
loadCmdBox();
}
private void CmdBoxPort_SelectedIndexChanged(object sender, EventArgs e)
{
handleComPort();
}
private void handleComPort()
{
// Set the right port for the selected item.
// The portname is based on the "COMx" part of the string (SelectedItem)
string item = CmdBoxPort.SelectedItem.ToString();
// Search for the expression "(COM" in the "selectedItem" string
if (item.Contains("(COM"))
{
// Get the index number where "(COM" starts in the string
int indexOfCom = item.IndexOf("(COM");
// Set PortName to COMx based on the expression in the "selectedItem" string
// It automatically gets the correct length of the COMx expression to make sure
// that also a COM10, COM11 and so on is working properly.
string PortName = item.Substring(indexOfCom + 1, item.Length - indexOfCom - 2);
if (serialMethods._serialPort.IsOpen)
{
serialMethods._serialPort.Close();
serialMethods.Connect(PortName);
label5.Text = "Active Port: " + PortName;
}
else
{
serialMethods.Connect(PortName);
label5.Text = PortName;
}
}
else
return;
}
private void loadCmdBox()
{
// Get all serial (COM)-ports you can see in the devicemanager
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2",
"SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
// Sort the items in the combobox
CmdBoxPort.Sorted = true;
// Add all available (COM)-ports to the combobox
foreach (System.Management.ManagementObject queryObj in searcher.Get().Cast<ManagementObject>())
{
CmdBoxPort.Items.Add(queryObj["Caption"]);
}
SerialPortService.PortsChanged += (sender1, changedArgs) => DetectChange(changedArgs.EventType);
label2.Text = "";
label3.Text = "";
label4.Text = "";
}
protected Task<Task> getSerPorts()
{
CmdBoxPort.Text = "";
CmdBoxPort.Update();
if (!String.IsNullOrEmpty(CmdBoxPort.Text))
{
handleComPort();
return Task.FromResult(Task.CompletedTask);
}
else
{
loadCmdBox();
return Task.FromResult(Task.CompletedTask);
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
SerialPortService.CleanUp();
this.Close();
}
private void RefreshButton_Click(object sender, EventArgs e)
{
refresh();
}
protected Task<Task> refresh()
{
label2.Text = "";
label3.Text = "";
label4.Text = "";
CmdBoxPort.Items.Clear();
getSerPorts();
return Task.FromResult(Task.CompletedTask);
}
protected virtual void DetectChange(EventType changedArgs)
{
if (changedArgs == EventType.Insertion)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at insertion invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
else if (changedArgs == EventType.Removal)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at removal invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
return;
}
}
public static class SerialPortService
{
private static SerialPort _serialPort;
private static string[] _serialPorts;
private static ManagementEventWatcher arrival;
private static ManagementEventWatcher removal;
private static readonly SerialMethods SD = new SerialMethods();
static SerialPortService()
{
_serialPorts = SerialPort.GetPortNames();
MonitorDeviceChanges();
}
public static void CleanUp()
{
arrival.Stop();
removal.Stop();
}
public static event EventHandler<PortsChangedArgs> PortsChanged;
private static void MonitorDeviceChanges()
{
try
{
var deviceArrivalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var deviceRemovalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
arrival = new ManagementEventWatcher(deviceArrivalQuery);
removal = new ManagementEventWatcher(deviceRemovalQuery);
arrival.EventArrived += (o, args) => RaisePortsChangedIfNecessary(EventType.Insertion);
removal.EventArrived += (sender, eventArgs) => RaisePortsChangedIfNecessary(EventType.Removal);
// Start listening for events
arrival.Start();
removal.Start();
}
catch (ManagementException err)
{
MessageBox.Show("Management exception = " + err, "Info", MessageBoxButtons.OK);
}
}
private static void RaisePortsChangedIfNecessary(EventType eventType)
{
lock (_serialPorts)
{
var availableSerialPorts = SerialPort.GetPortNames();
if (eventType == EventType.Insertion)
{
var added = availableSerialPorts.Except(_serialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, added));
}
else if (eventType == EventType.Removal)
{
var removed = _serialPorts.Except(availableSerialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, removed));
}
}
}
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
handler?.Invoke(sender, args);
}
}
public enum EventType
{
Insertion,
Removal,
}
public class PortsChangedArgs : EventArgs
{
private readonly EventType _eventType;
private readonly string[] _serialPorts;
public PortsChangedArgs(EventType eventType, string[] serialPorts)
{
_eventType = eventType;
_serialPorts = serialPorts;
}
public string[] SerialPorts => _serialPorts;
public EventType EventType => _eventType;
}
}
Just took a short look at this. It seems like getSerPorts() will always execute loadCmdBox() (CmdBoxPort.Text = ""; ... if (!String.IsNullOrEmpty(CmdBoxPort.Text))) that will attach a new event handler (previous attached event handlers will not be removed by attaching a new one).
You should either remove the existing event handler befor attaching a new one or only attach the event handler once.

Where should I put my variables in a Windows Forms Application without having to make it global? [duplicate]

This question already has answers here:
Model-View-Presenter in WinForms
(3 answers)
How to Structure a C# WinForms Model-View-Presenter (Passive View) Program?
(2 answers)
Closed 2 years ago.
I have a predicament! I don't know where I should put my variables in a C# Windows Forms Application. For example, in my WFA project I have a list of my own datatype object called "Item" and at the moment I've had to make it global, however, I understand global isn't the best of practises. Because I come from a C++ background I'd always create my variables in int main() and pass them to functions where needed. I honestly can't find an answer anywhere. Many thanks to anyone who can assist me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Sales_Calculator
{
public partial class Form1 : Form
{
//Should my list<Item> go here or is there a better place for it?
List<Item> objItems = new List<Item>();
public Form1()
{
InitializeComponent();
}
public class Item
{
private string m_sItemName;
private double m_dItemPrice;
private int m_iQuantitySold;
public Item(string sItemName, double dItemPrice, int iQuantitySold)
{
m_sItemName = sItemName;
m_dItemPrice = dItemPrice;
m_iQuantitySold = iQuantitySold;
}
public string Name
{
get { return m_sItemName; }
set { m_sItemName = value; }
}
public int QuantitySold
{
get { return m_iQuantitySold; }
set { m_iQuantitySold = value; }
}
public double Price
{
get { return m_dItemPrice; }
set { m_dItemPrice = value; }
}
}
bool DoesItemNameExist(string sName)
{
return (objItems.Find(delegate (Item objItem){return sName == objItem.Name;}) != null) ? true : false;
}
private Item HighestSellingItem()
{
int MaxQuantitySold = objItems.Max(objItem => objItem.QuantitySold);
return objItems.Find(delegate (Item objItem) {
return objItem.QuantitySold == MaxQuantitySold;
});
}
private double Average()
{
int iTotal = 0;
objItems.ForEach(delegate (Item objItem)
{
iTotal += objItem.QuantitySold;
});
double dAverage = iTotal / objItems.Count;
return dAverage;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void AddToDataGridView(object sender)
{
dgvItems.Rows.Add(objItems.Count, objItems.Last().Name, objItems.Last().QuantitySold, objItems.Last().Price);
}
void ClearTextBoxes()
{
txtItemName.Clear();
txtItemPrice.Clear();
txtQuantitySold.Clear();
}
void AddItemToList()
{
string sItemName = "";
if (DoesItemNameExist(sItemName = Convert.ToString(txtItemName.Text)))
{
MessageBox.Show("You can't have that name, it already exists!");
txtItemName.Clear();
return;
}
double dItemPrice = Convert.ToDouble(txtItemPrice.Text);
int iQuantitySold = Convert.ToInt32(txtQuantitySold.Text);
Item objItem = new Item(sItemName, dItemPrice, iQuantitySold);
objItems.Add(objItem);
MessageBox.Show("You have added an item!");
ClearTextBoxes();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
AddItemToList();
AddToDataGridView(sender);
lblAverageQuantitySold.Text = Average().ToString();
lblExistingItems.Text = objItems.Count.ToString();
}
catch (Exception ex)
{
MessageBox.Show("You have inputted incorrectly!", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
dvgHighestSellingItem.Rows.Clear();
dvgHighestSellingItem.Rows.Add(HighestSellingItem().Name);
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
}
}
}

C# Calculator Class

I was given this homework assignment, which I have been having a hard time with. The form was written and we had to write the class. Currently when I run the program my equals button does not appear to be working. I'm unsure why and I was wondering if someone could help me understand what I am missing. I believe I have written my class correctly. In my head what is going on is the calculator is calling the "currentValue" so I am constantly updating with the method I am using in my operators.
Am I in the right direction?
And why isn't my equals button calling the current value. The last time I ran this, if I typed 9 + 3 + then my display would populate with 12 and wait for me to enter the next number. So in theory why wouldn't my equals button load the answer? I believe I am calling the correct item yet I keep getting my initial entry. For instance if I typed 9 + 9 and hit = I keep getting 9.
Here is the calculator code (the part provided):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Calculator
{
public partial class frmCalculator : Form
{
public frmCalculator()
{
InitializeComponent();
}
// The following fields are used to store the value that's currently
// displayed by the calculator. displayString is a string value that's
// constructed as the user clicks numeric keys and the decimal and +/-
// key. The Convert.ToDecimal method is then used to convert this to a decimal
// field that's stored in displayValue.
private string displayString;
private decimal displayValue;
// The following bool fields are used to control numeric entry.
// newValue indicates whether the calculator is ready to receive a
// new numeric value. Once the user clicks a digit button, newValue is
// set to false. When the user clicks a button that "enters" the value,
// such as Add or Equals, newValue is set to true so the user can enter
// another value.
// decimalEntered is used to restrict the entry to a single decimal point.
// It is set to true whenever newValue is set to true, and it is set to
// false whenever the user clicks the decimal point button.
private bool newValue;
private bool decimalEntered;
private Calculator calc = new Calculator();
private void Form1_Load(object sender, System.EventArgs e)
{
displayValue = 0;
displayString = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
// This method handles the 0 through 9 keys, appending the digit clicked
// to the displayString field.
private void btnNumber_Click(object sender, System.EventArgs e)
{
if (newValue)
{
displayString = "";
newValue = false;
}
displayString += ((Button)sender).Tag.ToString();
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
}
// This method removes the last character from the displayString field.
private void btnBackSpace_Click(object sender, System.EventArgs e)
{
if (displayString.Length > 1)
{
displayString = displayString.Substring(0, displayString.Length - 1);
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
}
else
{
displayString = "";
displayValue = 0;
txtDisplay.Text = displayValue.ToString();
}
}
private void btnClear_Click(object sender, System.EventArgs e)
{
calc.Clear();
displayString = "";
displayValue = 0;
txtDisplay.Text = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
// This method appends a decimal point to the displayString field if the
// user has not already entered a decimal point.
private void btnDecimal_Click(object sender, System.EventArgs e)
{
if (newValue)
{
displayString = "0";
newValue = false;
}
if (!decimalEntered)
{
displayString += ".";
displayValue = Convert.ToDecimal(displayString);
txtDisplay.Text = displayValue.ToString();
decimalEntered = true;
}
}
private void btnSign_Click(object sender, System.EventArgs e)
{
displayValue = -displayValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnAdd_Click(object sender, System.EventArgs e)
{
calc.Add(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnSubtract_Click(object sender, System.EventArgs e)
{
calc.Subtract(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnMultiply_Click(object sender, System.EventArgs e)
{
calc.Multiply(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnDivide_Click(object sender, System.EventArgs e)
{
calc.Divide(displayValue);
newValue = true;
decimalEntered = false;
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnSqrt_Click(object sender, System.EventArgs e)
{
calc.SquareRoot(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
private void btnReciprocal_Click(object sender, System.EventArgs e)
{
try
{
calc.Reciprocal(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
}
catch (DivideByZeroException)
{
displayValue = 0;
txtDisplay.Text = "Cannot divide by zero.";
newValue = true;
decimalEntered = false;
}
}
private void btnEquals_Click(object sender, System.EventArgs e)
{
try
{
if (newValue)
calc.Equals();
else
calc.Equals(displayValue);
displayValue = calc.CurrentValue;
txtDisplay.Text = displayValue.ToString();
newValue = true;
decimalEntered = false;
}
catch (DivideByZeroException)
{
displayValue = 0;
txtDisplay.Text = "Cannot divide by zero.";
newValue = true;
decimalEntered = false;
}
}
}
}
Here is my class (The part I wrote):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Calculator
{
public class Calculator
{
public Decimal displayValue;
public Decimal currentValue;
public void Add(Decimal displayValue)
{
currentValue += displayValue;
}
public void Subtract(Decimal displayValue)
{
currentValue -= displayValue;
}
public void Multiply(Decimal displayValue)
{
currentValue *= displayValue;
}
public void Divide(Decimal displayValue)
{
currentValue /= displayValue;
}
public void SquareRoot(Decimal displayValue)
{
currentValue = (decimal)Math.Sqrt(Convert.ToDouble(displayValue));
}
public void Reciprocal(Decimal displayValue)
{
currentValue = 1 / displayValue;
}
public decimal Equals()
{
return currentValue;
}
public void Clear()
{
currentValue = 0;
displayValue = 0;
}
public decimal CurrentValue
{
get
{
return currentValue;
}
}
}
}
In the main code, you have called the Equal() method like this:
if (newValue)
calc.Equals();
else
calc.Equals(displayValue); //Your class do not have this.
So, you should do this first
//I am not sure why you need to pass in the displayValue parameter, so I presume it would not return anything.
public void Equal(Decimal displayValue)
{
//Do the things you suppose to do
}
And for your 9 + 9 = 9 problem, it is simply because in your code, you only press your click event Add_Button for once. Make a break point at your Add() method. Then try to do like this:
9 --> press your Add_Button --> 9 --> press your Add_Button --> check your currentValue
displayValue is both a class field and a method argument. Is that your intention? You need to make this.displayValue = ... when you assign to the field argument in order to make it clear what you are doing. Currently you are overwriting the local copy of the argument and the field value is always 0.
Just delete the decimal displayValue; declaration (and from the Clear() function) and then store the displayValue outside of the class in the form.
public class Calculator
{
//public Decimal displayValue;
public Decimal currentValue;
public void Add(Decimal displayValue)
{
currentValue+=displayValue;
}
...
public void Clear()
{
currentValue=0;
//displayValue=0;
}
public decimal CurrentValue
{
get { return currentValue; }
}
}
class Program
{
static void Main(string[] args)
{
Calculator calc=new Calculator();
calc.Add(1000m);
calc.Divide(25m);
calc.Subtract(8m);
Console.WriteLine(calc.CurrentValue);
// (1000/25)-8 = 32
}
}
The main problem I see with your code is that you are only adding one of your operands, So for example 8 + 8 will always equal 8 for example.You have to do something like this ( included Add and reciprocal functions only):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Calculator
{
public class Calculator
{
public Decimal displayValue;
public Decimal currentValue;
private Decimal Operand_1;
private Decimal Operand_2;
private bool Operand_1_Added = false;
private bool Operand_2_Added = false;
private string Operation = "";
private void AddOperand(Decimal Operand)
{
if(Operand_1_Added)
{
Operand_2 = Operand;
Operand_2_Added = true;
}
else {
Operand_1 = Operand;
Operand_1_Added = true;
currentValue = Operand_1;
}
}
public void Add(Decimal Arg1)
{
this.AddOperand(Arg1);
Operation = "Addition";
}
public void Reciprocal(Decimal Arg)
{
this.AddOperand(Arg);
Operation = "Reciprocal";
}
public void Clear()
{
currentValue = 0;
displayValue = 0;
Operand_1 = 0;
Operand_2 = 0;
}
public void Equals()
{
switch(Operation)
{
case "Addition":
currentValue = Operand_1 + Operand_2;
break;
case "Reciprocal":
currentValue = 1/Operand_1;
break;
default: break;
}
}
public void Equal(Decimal displayValue)
{
currentValue = displayValue;
}
public decimal CurrentValue
{
get
{
return currentValue;
}
}
}
Haven't tested code but this should work with the form class.
Let's look at the requirement:
"The results of multipication should show no more decimal places than the result of the first number than in the second number. Example 55.5*89.68 = 4977.240"
The natural of multiplication in basic arithmetic means that this happens by default anyway. Eg. you're never going to multiply X.X by X.XX and get result X.XXXXXXX... - it just can't happen.
Formatting is therefore easy - if you need to explicitly format then format as num.ToString("#.##############") which allows for a while bunch of numbers.
You haven't outlined any requirements for Division, so I can't comment.
BTW - if you say x = 1 / 3 and y = z * x, then you are going to get a lot of numbers after the decimal place, because x is .333333333... to start with. This is within the requirement AFAICT.

c# visual studio how to pass value from subclass to parent class?

I'm new here, and also new in C# programming in Visual Studio.
Currently I have an assignment about C# refactoring.
This is the original class
calculator.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HUANG_Kai_30077528_Assign1
{
public partial class calculator : Form
{
public calculator()
{
InitializeComponent();
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
}
private void calorieCalculation()
{
if (rbtnMale.Checked)
{
txtCalories.Text = (66
+ (6.3 * Convert.ToDouble(txtWeight.Text))
+ (12.9 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (6.8 * Convert.ToDouble(txtAge.Text))).ToString();
}
else
{
txtCalories.Text = (655
+ (4.3 * Convert.ToDouble(txtWeight.Text))
+ (4.7 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (4.7 * Convert.ToDouble(txtAge.Text))).ToString();
}
}
private void weightCalculation()
{
double maleVariable = 50;
double femaleVariable = 45.5;
double Formula = (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12) + Convert.ToDouble(txtInches.Text)));
if (rbtnMale.Checked)
{
txtIdealWeight.Text = ((maleVariable + Formula) * 2.2046).ToString();
}
else
{
txtIdealWeight.Text = ((femaleVariable + Formula) * 2.2046).ToString();
}
}
private void txtFeetValidation()
{
double feet;
if (!double.TryParse(txtFeet.Text, out feet))
{
MessageBox.Show("Feet must be a numeric value.");
txtFeet.Select();
if (!(Convert.ToDouble(txtFeet.Text) >= 5))
{
MessageBox.Show("Height has to be equal to or greater than 5 feet!");
txtFeet.Select();
return;
}
}
}
private void txtInchesValidation()
{
double inches;
if (!double.TryParse(txtInches.Text, out inches))
{
MessageBox.Show("Inches must be a numeric value.");
txtInches.Select();
return;
}
}
private void txtWeightValidation()
{
double weight;
if (!double.TryParse(txtWeight.Text, out weight))
{
MessageBox.Show("Weight must be a numeric value.");
txtWeight.Select();
return;
}
}
private void txtAgeValication()
{
double age;
if (!double.TryParse(txtAge.Text, out age))
{
MessageBox.Show("Age must be a numeric value.");
txtAge.Select();
return;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
txtFeetValidation();
txtInchesValidation();
txtWeightValidation();
txtAgeValication();
//Clear old results
txtIdealWeight.Text = "";
txtCalories.Text = "";
calorieCalculation();
weightCalculation();
}
private void label8_Click(object sender, EventArgs e)
{
}
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnAddPatient_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txtIdealWeight.Text))
{
Form secondForm = new patientInfo(this);
secondForm.Show();
}
else
{
MessageBox.Show("Please enter all datas and click on 'Add Patient' to add patient's records");
}
}
private void btnPatientList_Click(object sender, EventArgs e)
{
Form secondForm = new patientList(this);
secondForm.Show();
}
private void btnClear_Click(object sender, EventArgs e)
{
rbtnMale.Checked = false;
rbtnFemale.Checked = false;
txtFeet.Text = "";
txtInches.Text = "";
txtWeight.Text = "";
txtAge.Text = "";
txtCalories.Text = "";
txtIdealWeight.Text = "";
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
}
}
The following classed are the parent class and sub-classes I would like to setup.
parent: calculator.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HUANG_Kai_30077528_Assign1
{
public partial class calculator : Form
{
//private string maleCaloriesCalculation();
//private string maleWeightCalculation();
//private string femaleCaloriesCalculation();
//private string femaleWeightCalculation();
public calculator()
{
InitializeComponent();
}
private void rbtnMale_CheckedChanged(object sender, EventArgs e)
{
}
private void btnCalculate_Click(object sender, EventArgs e)
{
//Clear old results
txtIdealWeight.Text = "";
txtCalories.Text = "";
/* Validate User Input: */
//Validate height (feet) is numeric value
double result;
if (!double.TryParse(txtFeet.Text, out result))
{
MessageBox.Show("Feet must be a numeric value.");
txtFeet.Select();
return;
}
//Validate height (inches) is numeric value
if (!double.TryParse(txtInches.Text, out result))
{
MessageBox.Show("Inches must be a numeric value.");
txtInches.Select();
return;
}
//Validate weight is numeric value
if (!double.TryParse(txtWeight.Text, out result))
{
MessageBox.Show("Weight must be a numeric value.");
txtWeight.Select();
return;
}
//Validate age is numeric value
if (!double.TryParse(txtAge.Text, out result))
{
MessageBox.Show("Age must be a numeric value.");
txtAge.Select();
return;
}
if (!(Convert.ToDouble(txtFeet.Text) >= 5))
{
MessageBox.Show("Height has to be equal to or greater than 5 feet!");
txtFeet.Select();
return;
}
/*End validation*/
calculation();
}
private void calculation()
{
if (rbtnMale.Checked)
{
txtCalories.Text = maleCalculator.maleCalories().ToString();
//txtCalories.Text = maleCalculator.maleCaloriesCalculation();
//txtIdealWeight.Text = maleCalculator.maleWeightCalculation();
}
else
{
txtCalories.Text = femaleCalculator.femaleCaloriesCalculation();
txtIdealWeight.Text = femaleCalculator.femaleWeightCalculation();
}
}
private void btnClear_Click(object sender, EventArgs e)
{
rbtnMale.Checked = false;
rbtnFemale.Checked = false;
txtFeet.Text = "";
txtInches.Text = "";
txtWeight.Text = "";
txtAge.Text = "";
txtCalories.Text = "";
txtIdealWeight.Text = "";
}
}
}
subclass: maleCalculation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HUANG_Kai_30077528_Assign1
{
class maleCalculator: calculator
{
//private string maleCaloriesCalculation;
//private string maleWeightCalculation;
public maleCalculator maleCalories()
{
(66 + (6.3 * Convert.ToDouble(txtWeight.Text))
+ (12.9 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (6.8 * Convert.ToDouble(txtAge.Text))).ToString();
return maleCalories();
//this.txtCalories.Text = new maleCalculator.maleCalories;
}
public maleCalculator maleWeight()
{
((50 + (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12)
+ Convert.ToDouble(txtInches.Text)))) * 2.2046).ToString();
return maleWeight();
}
}
}
subclass: femaleCalculation.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HUANG_Kai_30077528_Assign1
{
class femaleCalculator : calculator
{
public double femaleCaloriesCalculation()
{
txtCalories.Text = (655 + (4.3 * Convert.ToDouble(txtWeight.Text))
+ (4.7 * ((Convert.ToDouble(txtFeet.Text) * 12)
+ Convert.ToDouble(txtInches.Text)))
- (4.7 * Convert.ToDouble(txtAge.Text))).ToString();
return femaleCaloriesCalculation();
}
public double femaleWeightCalculation()
{
txtIdealWeight.Text = ((45.5 + (2.3 * (((Convert.ToDouble(txtFeet.Text) - 5) * 12)
+ Convert.ToDouble(txtInches.Text)))) * 2.2046).ToString();
return femaleWeightCalculation();
}
}
}
As we can see, these two sub-classes are use to do the calculation for the calories and ideal weight. They are plan to take place of private void calorieCalculation() and private void weightCalculation() in the original class calculator.cs.
The function I need is like this:
When I execute the program and need to calculate the idealWeight and calories, the parent class calculator.cs will get the result from the formula contain in the sub-class, and ToString in the text box. That's why there are txtCalories and txtIdealWeight inside the calculator.cs.
So the question is how to get the results in the sub-class, and fill in the text boxes?
Guys, please help me with it as this is really important to me!!
Thank you all!!
Do you mean a virtual function? If so,
class Ancestor
{
public virtual int DoSomething()
{
// execute commands here.
// for now just throw exception.
throw new NotImplementedException();
}
}
class Derived_A : Ancestor
{
public override int DoSomething()
{
return 1 + 1;
}
}
class Derived_B : Ancestor
{
public override int DoSomething()
{
return 1 + 2;
}
}
This is ancestry, with virtual functions. For more on this:
Practical usage of virtual functions in c#
http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx
This type of code can also be done with interfaces. See http://msdn.microsoft.com/en-us/library/vstudio/ms173156.aspx.

display information about an object selected in a listbox in textboxes

I want to display the information about whichever flight is selected in the listbox in textboxes next to it. My problem is I can't get my curFlight variable to work right gives me InvalidCastException was unhandled error and says When casting froim a number, the value must be a number less than infinity.
heres my form code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Reservations
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Flight curFlight;
Flight flight1 = new Flight("Cessna Citation X", "10:00AM", "Denver", 6, 2);
Flight flight2 = new Flight("Piper Mirage", "10:00PM", "Kansas City", 3, 2);
private void Form1_Load(object sender, EventArgs e)
{
MakeReservations();
DisplayFlights();
}
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
txtDepart.Text = curFlight.DepartureTime;
txtDestination.Text = curFlight.Destination;
}
private void MakeReservations()
{
flight1.MakeReservation("Dill", 12);
flight1.MakeReservation("Deenda", 3);
flight1.MakeReservation("Schmanda", 11);
flight2.MakeReservation("Dill", 4);
flight2.MakeReservation("Deenda", 2);
}
private void DisplayFlights()
{
lstFlights.Items.Clear();
lstFlights.Items.Add(flight1.Plane);
lstFlights.Items.Add(flight2.Plane);
}
private void btnMakeReservation_Click(object sender, EventArgs e)
{
string name;
int seatNum;
name = txtCustomerName.Text;
seatNum = Convert.ToInt16(txtSeatNum.Text);
curFlight.MakeReservation(name, seatNum);
}
}
}
HERES THE CLASS CODE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Reservations
{
class Flight
{
private string mPlane;
private string mDepartureTime;
private string mDestination;
private int mRows;
private int mSeats;
private string[] mSeatChart;
public Flight()
{
}
public Flight(string planeType, string departureTime, string destination, int numRows, int numSeatsPerRow)
{
this.Plane = planeType;
this.DepartureTime = departureTime;
this.Destination = destination;
this.Rows = numRows;
this.Seats = numSeatsPerRow;
// create the seat chart array
mSeatChart = new string[Rows * Seats];
for (int seat = 0; seat <= mSeatChart.GetUpperBound(0); seat++)
{
mSeatChart[seat] = "Open";
}
}
public string Plane
{
get { return mPlane; }
set { mPlane = value; }
}
public string DepartureTime
{
get { return mDepartureTime; }
set { mDepartureTime = value; }
}
public string Destination
{
get { return mDestination; }
set { mDestination = value; }
}
public int Rows
{
get { return mRows; }
set { mRows = value; }
}
public int Seats
{
get { return mSeats; }
set { mSeats = value; }
}
public string[] SeatChart
{
get { return mSeatChart; }
set { mSeatChart = value; }
}
public void MakeReservation(string name, int seat)
{
if (seat <= (Rows * Seats) && mSeatChart[seat - 1] == "Open")
{
mSeatChart[seat - 1] = name;
}
else
{
//let calling program know it didnt work.
}
}
public bool IsFull()
{
return false;
}
}
}
The reason you are getting the error is because you are assigning a string to the listbox and then trying to cast that string to a Flight Object
lstFlights.Items.Add(flight1.Plane); // Just say it is named "Plane 1"
lstFlights.Items.Add(flight2.Plane); // Just say it is named "Plane 2"
curFlight = (Flight)lstFlights.SelectedItem; // Now you are trying to convert "Plane 2" into a flight object which is incorrect
Try this instead
Add a Global List of type flights
List<Flight> flightList = new List<Flight>();
Flight flight1 = new Flight("Cessna Citation X", "10:00AM", "Denver", 6, 2);
Flight flight2 = new Flight("Piper Mirage", "10:00PM", "Kansas City", 3, 2);
in your form load add SetupFlights
private void Form1_Load(object sender, EventArgs e)
{
MakeReservations();
DisplayFlights();
SetupFlights(); // added this line
}
private void SetupFlights()
{
flightList.Add(flight1);
flightList.Add(flight2);
}
and your selected Index Changed should be something like this
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = flightList.FirstOrDefault(x => x.Plane == lstFlights.SelectedItem.ToString()); // Changed this line
txtDepart.Text = curFlight.DepartureTime;
txtDestination.Text = curFlight.Destination;
}
Although the answer by MVCKarl is more general, I'll show an easier way, which could suit in simple cases.
You could simply override ToString for the Flight class:
class Flight
{
//your code
public override string ToString()
{
//or anything you want to display
return this.Plane;
}
}
Then edit DisplayFlights method to add flights into the list:
private void DisplayFlights()
{
lstFlights.Items.Clear();
lstFlights.Items.Add(flight1);
lstFlights.Items.Add(flight2);
}
After this your lstFlights_SelectedIndexChanged would start working as expected:
private void lstFlights_SelectedIndexChanged(object sender, EventArgs e)
{
curFlight = (Flight)lstFlights.SelectedItem;
textBox1.Text = curFlight.DepartureTime;
textBox2.Text = curFlight.Destination;
}

Categories