First post, long time reader.
I'm currently learning C# with "Head First C#" (I'm up to Encapsulation and Get/Set properties)
I'm writing a small program to work with pictures for a friend, I'm just wondering if I'm heading along the right lines with my PictureController class? My main problem is that I am setting a lot of form items with this class, and it feels unnatured to keep referencing form items from within the class, I'm pasting my code below, if you could let me know if I'm doing anything wrong then I'd be most grateful :)
Many thanks!
PictureController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace PictureController
{
class PictureController
{
private int arrayPosition = 0;
private int numFiles = 0;
private string[,] arrayPictures;
public PictureBox myPictureBox;
public RadioButton myCopyButton;
public RadioButton myDeleteButton;
public TextBox mySource;
public ComboBox myDestinations;
private FolderBrowserDialog sourceFolder;
private FolderBrowserDialog destFolder;
public void InitialisePicture()
{
if (arrayPictures != null && arrayPictures.Length > 0)
{
myPictureBox.ImageLocation = arrayPictures[arrayPosition, 0];
}
else
{
MessageBox.Show("The folder you have selected contains no pictures...");
myPictureBox.ImageLocation = null;
}
}
public void NavigatePicture(int direction)
{
if (arrayPosition + direction >= 0 && arrayPosition + direction < numFiles)
{
arrayPosition += direction;
myPictureBox.ImageLocation = arrayPictures[arrayPosition, 0];
myCopyButton.Checked = Convert.ToBoolean(arrayPictures[arrayPosition, 1]);
myDeleteButton.Checked = Convert.ToBoolean(arrayPictures[arrayPosition, 2]);
}
}
public void UpdateActions(bool copyChecked, bool deleteChecked)
{
if (arrayPictures != null)
{
arrayPictures[arrayPosition, 1] = copyChecked.ToString();
arrayPictures[arrayPosition, 2] = deleteChecked.ToString();
}
}
public void GetFiles()
{
sourceFolder = new FolderBrowserDialog();
sourceFolder.ShowDialog();
if (sourceFolder.SelectedPath != "")
{
string[] arrayTempFiles = Directory.GetFiles(sourceFolder.SelectedPath,"*.jpg");
numFiles = arrayTempFiles.Length;
arrayPictures = new string[arrayTempFiles.Length,3];
for (int i = 0; i < arrayTempFiles.Length; i++)
{
arrayPictures[i, 0] = arrayTempFiles[i];
arrayPictures[i, 1] = "false";
arrayPictures[i, 2] = "false";
}
mySource.Text = sourceFolder.SelectedPath;
InitialisePicture();
}
}
public void AddDestinationFolder()
{
destFolder = new FolderBrowserDialog();
destFolder.ShowDialog();
if (destFolder.SelectedPath != "")
{
myDestinations.Items.Add(destFolder.SelectedPath);
}
}
}
}
Form1.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 PictureController
{
public partial class Form1 : Form
{
PictureController PicControl;
public Form1()
{
InitializeComponent();
PicControl = new PictureController() { myPictureBox = pbPhoto, myCopyButton = rbMove, myDeleteButton = rbDelete, mySource = tbSource, myDestinations = cbDestination };
}
private void btnPrev_Click(object sender, EventArgs e)
{
PicControl.NavigatePicture(-1);
}
private void btnNext_Click(object sender, EventArgs e)
{
PicControl.NavigatePicture(1);
}
private void rbMove_CheckedChanged(object sender, EventArgs e)
{
if (rbMove.Checked || rbDelete.Checked)
{
PicControl.UpdateActions(rbMove.Checked, rbDelete.Checked);
}
}
private void rbDelete_CheckedChanged(object sender, EventArgs e)
{
if (rbMove.Checked || rbDelete.Checked)
{
PicControl.UpdateActions(rbMove.Checked, rbDelete.Checked);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.A:
PicControl.NavigatePicture(-1);
break;
case Keys.D:
PicControl.NavigatePicture(1);
break;
case Keys.W:
rbMove.Checked = true;
break;
case Keys.S:
rbDelete.Checked = true;
break;
}
}
private void btnGetFiles_Click(object sender, EventArgs e)
{
PicControl.GetFiles();
}
private void btnProcess_Click(object sender, EventArgs e)
{
}
private void btnAddDest_Click(object sender, EventArgs e)
{
PicControl.AddDestinationFolder();
}
}
}
I don't see the reason to use Controls in your PictureController class. You should only use non-forms datatypes there and handle the interaction in your Form, offering events and methods from your PictureController class to react and act on it.
It's a good start in my opinion.
Hard to tell if you're doing something "wrong" because it depends what you think is right, every programmer has his/her own style and best practice set and as long as the code is working and efficient it's "right". There are many roads leading to Rome. :)
Anyway if you ask for personal opinion or advice, I would make two major changes in logic:
Have the Controller be a static class (Singleton if you prefer)
Don't pass or use the form controls directly. Instead pass the instance of your form to the static class in some Initialize method, then use that instance and call public method that is working with the controls directly.
Example for the second change:
public static void NavigatePicture(int direction)
{
if (arrayPosition + direction >= 0 && arrayPosition + direction < numFiles)
{
arrayPosition += direction;
_formInstance.SetPictureLocation(arrayPictures[arrayPosition, 0]);
_formInstance.SetCopyStatus(Convert.ToBoolean(arrayPictures[arrayPosition, 1]));
_formInstance.SetDeleteStatus(Convert.ToBoolean(arrayPictures[arrayPosition, 2]));
}
}
//...and in the form:
public SetPictureLocation(sLocation)
{
myPictureBox.ImageLocation = sLocation;
}
What is the point of having the controller, just encapsulate the extra logic out of the form? Do you need your controller to be testable? Do you want to use an abstract model of your business logic? If you answer yes to last 2 questions you might want to google:
a. MVC pattern
b. MVP pattern
Everything is wrong.
Controller (if it is a controller of the form/window) should know about form while in your sample - form know about controller.
Controller should know how to build data / and handle some form events when in your sample controller have references to pictureBox'es etc.
And there are no need to "extract" controller from the control code, while doesn't established what the "data/model" of the control is (and not framed with the type).
It's not clear what is the data there: path or image collection.
Related
Please Help, I'm a complete noob. However, i'm working with some complicated API.
I have external class:
namespace IB_CSharp_RealTime_WinForms_CS
{
//! [ewrapperimpl]
public class EWrapperImpl : EWrapper
{
...
//! [historicaldata]
public virtual void historicalData(int reqId, string date, double open, double high, double low, double close, int volume, int count, double WAP, bool hasGaps)
{
Console.WriteLine("HistoricalData. "+reqId+" - Date: "+date+", Open: "+open+", High: "+high+", Low: "+low+", Close: "+close+", Volume: "+volume+", Count: "+count+", WAP: "+WAP+", HasGaps: "+hasGaps);
}
...
And I have a Form
namespace IB_CSharp_RealTime_WinForms_CS
{
public partial class Form1 : Form
{
...
How can I pass "double high" from my external class to my Form?
Thank you in advance!
My full code:
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;
using System.Threading; // Add this for multi-threading support
using IBApi; // Add this for IB API Support
namespace IB_CSharp_RealTime_WinForms_CS
{
public partial class Form1 : Form
{
// This delegate enables asynchronous calls for setting
// the text property on a ListBox control.
delegate void SetTextCallback(string text);
public void AddListBoxItem(string text)
{
// See if a new invocation is required form a different thread
if (this.lbData.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(AddListBoxItem);
this.Invoke(d, new object[] { text });
}
else
{
// Add the text string to the list box
this.lbData.Items.Add(text);
}
}
// Create the ibClient object to represent the connection
// This will be used throughout the form
IB_CSharp_RealTime_WinForms_CS.EWrapperImpl ibClient;
private string tickerId;
public Form1()
{
InitializeComponent();
// Instantiate the ibClient
ibClient = new IB_CSharp_RealTime_WinForms_CS.EWrapperImpl();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnConnect_Click(object sender, EventArgs e)
{
ibClient.ClientSocket.eConnect("", 7496, 0);
var reader = new EReader(ibClient.ClientSocket, ibClient.Signal);
reader.Start();
new Thread(() => {
while (ibClient.ClientSocket.IsConnected())
{
ibClient.Signal.waitForSignal();
reader.processMsgs();
}
})
{ IsBackground = true }.Start();
while (ibClient.NextOrderId <= 0) { }
// Set up the form object in the EWrapper
ibClient.myform = (Form1)Application.OpenForms[0];
}
private void btnDisconnect_Click(object sender, EventArgs e)
{
// Disconnect from interactive Brokers
ibClient.ClientSocket.eDisconnect();
}
private void btnStart_Click(object sender, EventArgs e)
{
// Create a new contract to specify the security we are searching for
IBApi.Contract contract = new IBApi.Contract();
// Create a new TagValueList object (for API version 9.71 and later)
List < IBApi.TagValue > mktDataOptions = new List<IBApi.TagValue>();
// Set the underlying stock symbol from the tbSymbol text box
contract.Symbol = tbSymbol.Text;
// Set the Security type to STK for a Stock
contract.SecType = "STK";
// Use "SMART" as the general exchange
contract.Exchange = "SMART";
// Set the primary exchange (sometimes called Listing exchange)
// Use either NYSE or ISLAND
contract.PrimaryExch = "ISLAND";
// Set the currency to USD
contract.Currency = "USD";
// Kick off the subscription for real-time data (add the mktDataOptions list for API v9.71)
ibClient.ClientSocket.reqMktData(1, contract, "", false, mktDataOptions);
// For API v9.72 and higher, add one more parameter for regulatory snapshot
// ibClient.ClientSocket.reqMktData(1, contract, "", false, false, mktDataOptions);
} // end btnStart_Click
private void btnStop_Click(object sender, EventArgs e)
{
// Make the call to cancel the market data subscription
ibClient.ClientSocket.cancelMktData(1);
}
}
}
What I want is TextBox1.Text to show the value of "high". Basically if I can learn on how to pass that value I can use it to pass all other values.
I have been recently learning C# and have a problem I just cant seem to wrap my head around. Please forgive me if this is noobish as I am very new to C# but my question is about delegates and invoke.
I have read many many tutorials online and watched many video tutorials about this as well but I am still getting the same error in my code and I just dont seem to grasp the subtleties. As I understand it a delegate is a pointer to a function and can be used to invoke that function from say another thread to update a textbox. I understand creating a delegate, that much I think I am doing right but when I invoke the delegate from a threat I always get the error Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on.
The callback appears to be functional as it is calling the function that it is designed to however it does not seem to do it on the correct thread which I thought was the whole point of doing it this way. I know there is the option to set that warning break to false but I would rather learn what I am doing wrong and how to code this type of method properly. I appreciate any help, suggestions or answers you can provide as I am not sure any more of the tutorials are getting me any closer at this point to understanding where I have gone wrong.
My code is very basic and as I am just trying to understand the most basic concepts of properly coding for multithreading. Below is my code.
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;
using System.Media;
using System.Threading;
using System.Reflection;
namespace WindowsFormsApplication3
{
//declair delegate name(vars) CORRECT
public delegate void Textboxdelegate(Int64 MyVar);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
runme();
}
public void runme()
{
textBox1.Text = "87";
textupdate(44);
int target = 0;
Textboxdelegate TD = new Textboxdelegate(textupdate);
Number number = new Number(target, TD);
TD(11);
Thread thread1 = new Thread(new ThreadStart(number.worker));
thread1.Start();
}
public void textupdate(Int64 cntr)
{
textBox1.Text += cntr.ToString();
}
}
class Number
{
int _target;
Textboxdelegate _callbackMethod;
public Number(int target, Textboxdelegate TDD)
{
this._target = target;
this._callbackMethod = TDD;
}
public void worker()
{
Int64 counter = 0;
byte[] lifeforms = new byte[2146435071];
for (long y = 1; y <= 2146; y++)
{
for (long X = 1; X <= 1000000; X++)
{
lifeforms[X * y] = 20;
}
counter += 1;
if(_callbackMethod != null)
{
_callbackMethod(counter);
}
}
MessageBox.Show("Done!");
}
}
}
This crude example should do it for what you want to do:
//public delegate void Textboxdelegate(Int64 MyVar);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Action<Int64> Textboxdelegate;
public void runme()
{
textBox1.Text = "87";
textupdate(44);
int target = 0;
Textboxdelegate = textupdate;
Number number = new Number(target, Textboxdelegate,this);
Textboxdelegate(11);
Thread thread1 = new Thread(new ThreadStart(number.worker));
thread1.Start();
}
public void textupdate(Int64 cntr)
{
textBox1.Text += cntr.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
runme();
}
}
class Number
{
int _target;
Action<Int64> _callbackMethod;
Form1 frm;
public Number(int target, Action<Int64> act,Form1 frm)
{
this._target = target;
this._callbackMethod = act;
this.frm = frm;
}
public void worker()
{
Int64 counter = 0;
byte[] lifeforms = new byte[214643507];
for (long y = 1; y <= 2146; y++)
{
for (long X = 1; X <= 100000; X++)
{
lifeforms[X * y] = 20;
}
counter += 1;
if (_callbackMethod != null)
{
if (frm.InvokeRequired)
{
frm.Invoke(_callbackMethod,new object[]{counter});
}
else
{
_callbackMethod(counter);
}
}
}
MessageBox.Show("Done!");
}
}
Controls have thread-afinity,meaning they can only be accessed from the thread that created them,and you where accessing them by another thread.Now the Invoke method of the Control class(the base of form and all its controls)will allow you to safelly access them(very summarized explanation).
I have setup an Class that holds names/Numbers/ect, and created a List of objects to hold them. I want to display them on a second Form in a ListView. Right now I am using a getter like...
public List<Employee> GetEmpList(){
return EmployeeList;
}
Then in the second Form's constructor I am using the Form1.GetEmpList() like...
DisplayForm{
InitializeComponent();
LoadEmployees(EmployeeAddition.GetList());
}
I am getting and error saying "an object reference is required for the nonstatic field". The method I am calling is non-static, and returns a reference to the List in the Form1 class. I have even tried to just make the List public and calling using Form1.List but it still gives me the same error.
Is there a way to pass a List between Form classes or is it impossible?
EDIT: Poeple said that more information was needed. I didn't want to copy paste all the code here, but I am going to put a good chunk just because I am new and not quite sure what is relevant and what is not. (I am taking a class, but remotely, and my teacher is...well a remote teacher, useless. She actually told me to ask here)
I guess I am missing how to instatize a method, I thought that when the object was created from the class the method became part of the object. The Method is part for the Form1 (Renamed but thats what it is) class/object. I will dumb the code under here, I don't know if that is frowned upon; if so I am sorry.
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 EmplyeeList
{
public partial class EmployeeDisplay : Form
{
public EmployeeDisplay()
{
InitializeComponent();
LoadEmployees(EmployeeAddition.GetList());
}
private void LoadEmployees(IList<CorpEmployee> emp)
{
foreach (CorpEmployee ce in emp)
{
ListViewItem lvi = new ListViewItem();
lvi.SubItems.Add(ce.Name);
lvi.SubItems.Add(ce.Address);
lvi.SubItems.Add(ce.PhoneNumber);
lvi.SubItems.Add(ce.ServiceArea);
lvi.SubItems.Add(ce.EmplNumber.ToString());
lvi.SubItems.Add(ce.RoomNumber.ToString());
lvi.SubItems.Add(ce.PhoneExt.ToString());
lvi.SubItems.Add(ce.email);
displayListView.Items.Add(lvi);
}
}
private void closeButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
This is the first Form class to load...
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 EmplyeeList
{
public class EmployeeAddition : Form
{
//Create a list to hold CorpEmployee objects.
private List<CorpEmployee> CorpEmplList = new List<CorpEmployee>();
public EmployeeAddition()
{
InitializeComponent();
}
private void saveButton_Click(object sender, EventArgs e)
{
int testingNum; //Used for output in parsing numbers
//If statments are used to make sure ints are ints, and nothing is blank.
if (Int32.TryParse(employeeNumTextBox.Text, out testingNum) || ! (employeeNumTextBox.Text == ""))
{
if (Int32.TryParse(roomNumTextBox.Text, out testingNum) || !(roomNumTextBox.Text == ""))
{
if (Int32.TryParse(phoneExtTextBox.Text, out testingNum) || !(phoneExtTextBox.Text == ""))
{
if (!(nameTextBox.Text == "") || !(addressTextBox.Text == "") || !(titleTextBox.Text == "") || !(phoneNumberTextBox.Text == "") ||
!(serviceAreaTextBox.Text == "") || !(emailTextBox.Text == ""))
{
//If all fields are filled in right then we add the object to the List
CorpEmplList.Add(CreateCorpEmployee(nameTextBox.Text, addressTextBox.Text, titleTextBox.Text,
phoneNumberTextBox.Text, serviceAreaTextBox.Text,
Convert.ToInt32(employeeNumTextBox.Text), Convert.ToInt32(roomNumTextBox.Text),
Convert.ToInt32(phoneExtTextBox.Text), emailTextBox.Text));
//Let the user know it was added
MessageBox.Show("Employee was added!");
//Clear fields
ClearAllFields();
}
else
{
MessageBox.Show("All fields must be filled in.");
}
}
else
{
MessageBox.Show("Phone Ext.# should be a number");
}
}
else
{
MessageBox.Show("Check your Room# and try again.");
}
}
else
{
MessageBox.Show("Employee Number Should be a number.");
}
}
//This takes in all the employee fields and returns a contructed object
private CorpEmployee CreateCorpEmployee(String name, String address, String title, String phoneNumber,
String serviceArea, int emplNumber, int roomNumber, int phoneExt, String email)
{
CorpEmployee corpEmpObject = new CorpEmployee(name, address, title, phoneNumber, serviceArea, emplNumber, roomNumber, phoneExt, email);
return corpEmpObject;
}
//This just clears all the fiels
private void ClearAllFields()
{
nameTextBox.Text = "";
addressTextBox.Text = "";
titleTextBox.Text = "";
phoneNumberTextBox.Text = "";
serviceAreaTextBox.Text = "";
employeeNumTextBox.Text = "";
roomNumTextBox.Text = "";
phoneExtTextBox.Text = "";
emailTextBox.Text = "";
}
//This returns the List of CorpEmployees
public List<CorpEmployee> GetList()
{
return CorpEmplList;
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
private void clearButton_Click(object sender, EventArgs e)
{
ClearAllFields();
}
private void showButton_Click(object sender, EventArgs e)
{
EmployeeDisplay ed = new EmployeeDisplay();
ed.Show();
}
}
}
After relooking at the code I think I might see what you are saying about calling it from a static class, not an object. Is there a way to find the name of the Object that the Compiler creates from the first Form?
The first problem you are having is you are treating the GetEmpList() function as an static method. It is not static and probably shouldn't be static. That is why people are saying you need to create an instance of it. However, looking at what you are asking the way you are going about this is probably flawed in a more fundamental way that just creating a new version of the form will solve. The problem is you want to pass model data between forms. Without more information it is really hard to tell how you want this all to go together. However you probably already have an instance of the EmployeeAddition form and don't need to create another instance inside the constructor of your DisplayForm. Instead what you should do is make the LoadEmployees method public and pass the results of GetEmpList() into that.
So your structure would be more like
public class EmployeeAddition : Form {
...
public List<Employee> GetEmpList(){
return EmployeeList;
}
...
public void ShowDisplayForm(){
var displayForm = new DisplayForm();
displayForm.LoadEmployees(GetEmpList());
displayForm.Show();
}
...
}
Of course this structure may be slightly off as I'm guessing at which form will own which form but this is closer to what you want.
try use "new"
DisplayForm{
InitializeComponent();
EmployeeAddition = new EmployeeAdditionClass();
LoadEmployees(EmployeeAddition.GetList());
}
I can't figure out why this keeps happening. I'm a beginner but to me there is a reference set to an instance. I had trouble at first getting the class to have a size for the array which is now set to 100
Here is my code.
Form1.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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
SalesmanClass[] salesmen = new SalesmanClass[100];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox6.Text.Trim().Length != 0)
{
for (int i = 0; i <= salesmen.Length; i++)
{
if (salesmen[i] == null)
{
salesmen[i].name = textBox6.Text; // error happens here when i enter something into the form it says
//Object reference not set to an instance of an object error
break;
}
}
}
else
{
MessageBox.Show("Please Input a Name");
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
List<string> names = new List<string>();
for (int i = 0; i < salesmen.Length; i++)//var salesmen in salesmen)
{
names.Add(salesmen[i].Name);// same problem here
}
listBox1.Items.Add(names);
}
private void textBox6_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click_1(object sender, EventArgs e)
{
}
}
}
SalesmanClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public class SalesmanClass
{
public string name;
public string cNum;
public string Email;
public string address;
public string gArea;
public int tSales;
public SalesmanClass()
{
name = null;
cNum = null;
Email = null;
address = null;
gArea = null;
}
You use the == operator in your if statement, meaning that if the salesman IS null, set its name. I believe you meant that if the salesman is not null (!=). You're also going to encounter an index out of range exception in your for loop, so I've fixed that here as well.
for (int i = 0; i < salesmen.Length; i++)
{
if (salesmen[i] != null)
{
salesmen[i].name = textBox6.Text; // error happens here when i enter something into the form it says
//Object reference not set to an instance of an object error
break;
}
}
If you did mean for that instance to be null, perhaps you want something like this:
for (int i = 0; i < salesmen.Length; i++)
{
if (salesmen[i] == null)
{
salesmen[i] = new SalesmanClass();
salesmen[i].name = textBox6.Text; // error happens here when i enter something into the form it says
//Object reference not set to an instance of an object error
break;
}
}
In your button2_Click method, you are encountering the same issue because you aren't skipping the null salesmen. You can also see that I commented that I changed the field which you are accessing from Name to name since in the class which you posted, there is no Name field.
private void button2_Click(object sender, EventArgs e)
{
List<string> names = new List<string>();
for (int i = 0; i < salesmen.Length; i++)//var salesmen in salesmen)
{
if (salesmen[i] != null)
{
names.Add(salesmen[i].name); // changed from .Name to .name
}
}
listBox1.Items.Add(names);
}
Just remember that this line doesn't create any new SalesmanClass objects, only 100 references of type SalesmanClass.
SalesmanClass[] salesmen = new SalesmanClass[100];
I think you want:
if (salesmen[i] == null)
{
salesmen[i] = new SalesmanClass();
salesmen[i].name = textBox6.Text;
break;
}
[EDIT]
Lander beat me to it. What I would suggest is you use a List, the you don't have to worry about "empty spots"
List<Salesman>() salesmen = new List<Salesman>();
And then replace your for loop code with simply:
if (textBox6.Text.Trim().Length != 0)
{
salesmen.Add(new Salesmane() { name = textBox6.Text } );
}
else
{
MessageBox.Show("Please Input a Name");
}
You use this further down in List<string> names.
You might have to declare getters and setters on your properties:
public string Name { get; set; }
I would also make these property names CamelCase since that is the accepted standard.
You'll need to update your button2_click to use Count instead of Length or use a foreach loop:
foreach (Salesman salesman in salesmen)
{
names.Add(salesman.Name);
}
You can also use LINQ to simplify, this does exactly the same ting:
List<string> names = salesmen.Select(s => s.Name).ToList();
if an object reference error occurs check whether the variable u pass is correctly matching the correct index eg : If you are using Grid check whether the variable u access correctly pointing the index of the grid.
int StudID =
Convert.ToInt32(editableItem.OwnerTableView.DataKeyValues[editableItem.ItemIndex]
["StudID"].ToString());
I am trying to learn classes, meaning writing codes outside of the windows form and calling that code in the form. I created a basic calculation in the form and it works. The problem is, I want to know how I can move the entire calculation into a class and call it into the form on load or when a control is click. It does not work!
Here is my local or form version which works:
Please note that the form will load with the first calculation because the Radiobutton is checked on load.
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 Calculations
{
public partial class Calculations : Form
{
public Calculations()
{
InitializeComponent();
}
public decimal SalesTax = 0.065M;
public decimal AppliedTax;
public decimal Price;
public decimal SubTotal;
public decimal GrandTotal;
public object Calc()
{
Int32 GetQuantity = Convert.ToInt32(txtQuantity.Text);
SubTotal = (Price * GetQuantity);
AppliedTax = (SubTotal * SalesTax);
GrandTotal = (SubTotal + AppliedTax);
if (radRed.Checked == true)
{
Price = 100;
}
else if (radBlue.Checked == true)
{
Price = 200;
}
else if (radGreen.Checked == true)
{
Price = 300;
}
lblPrice.Text = GrandTotal.ToString("c");
return GrandTotal;
}
private void Calculations_Load(object sender, EventArgs e)
{
txtQuantity.Text = "10";
radRed.Checked = true;
Calc();
}
private void radRed_CheckedChanged(object sender, EventArgs e)
{
Calc();
}
private void radBlue_CheckedChanged(object sender, EventArgs e)
{
Calc();
}
private void radGreen_CheckedChanged(object sender, EventArgs e)
{
Calc();
}
private void btnCalculate_Click(object sender, EventArgs e)
{
Calc();
}
}
}
And here is my attempt to place all of this in a class:
It works but not on load, you have to check another radiobutton first
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Calculations
{
class ClsCalc
{
class ClsRef
{
public static Calculations FormCtrls
{
get
{
return Calculations.ActiveForm as Calculations;
}
}
}
public static decimal SalesTax = 0.065M;
public static decimal AppliedTax;
public static decimal Price;
public static decimal SubTotal;
public static decimal GrandTotal;
public static object Calc()
{
Int32 GetQuantity = Convert.ToInt32(ClsRef.FormCtrls.txtQuantity.Text);
SubTotal = (Price * GetQuantity);
AppliedTax = (SubTotal * SalesTax);
GrandTotal = (SubTotal + AppliedTax);
if (ClsRef.FormCtrls.radRed.Checked == true)
{
Price = 100;
}
else if (ClsRef.FormCtrls.radBlue.Checked == true)
{
Price = 200;
}
else if (ClsRef.FormCtrls.radGreen.Checked == true)
{
Price = 300;
}
ClsRef.FormCtrls.lblPrice.Text = GrandTotal.ToString("c");
return GrandTotal;
}
}
}
Finally I called it in the form Load event:
ClsCalc.Calc();
Please note this is not a real project just a way to learn, well for me that is.
Thank you!
Your calculation method is almost entirely involving interactions with UI elements. You gather a bunch of information from a textbox and various checkboxes, and then have just three lines of actual calculations, and then you display the results.
UI interaction shouldn't be moved outside of the form. You shouldn't expose the internal controls of a form publicly; they should only ever be accessed from within their parent form (or user control, if that's the case).
A common pattern that you'll see when performing some form submit operation is to gather information from input controls, do some calculations on the data, and then display the results on the form. Both the gathering information and displaying results should stay within the form, the only thing that you should (potentially) move outside of the form's definition is the calculations. In this case that's such a small amount of work there just isn't a compelling reason to do that.