I have a program in which the user inputs information into two separate text boxes and then clicks a button, at which time the program does some work and returns data to a third text box.
Then the user enters data into another textbox and clicks a second button. The program takes the text box return data from the first button click method along with the new input data, does some work and returns data to a mutli-line text box.
The problem I am having is that once the program leaves the first button click method, the return data disappears, so no data from the first button click method gets passed to the second button click method.
I am pretty sure it does this because the object is instantiated inside of the first button click method instead of being instantiated at the class level and therefore once the program leaves the method the object is gone. I attempted to instantiate the object at the class level but I cannot because I receive a "field initializer cannot reference the non-static field, method, or property" error.
I have looked at the MSDN specifications for this problem and understand what causes it, but the answer they give to fix it is to instantiate the object inside of the method. So I am right back to where I started from.
I am at a loss on what to do here. Here is my code with the object instantiated inside of the button click method:
private void btnOrderButton_Click(object sender, EventArgs e)
{
numberOfPizzas = int.Parse(this.txtNumberOfPizzaOrdered.Text);
numberOfCokes = int.Parse(this.txtNumberOfCokesOrdered.Text);
PizzaOrder orderObject = new PizzaOrder(numberOfPizzas, numberOfCokes);
this.txtAmountDue.Text = orderObject.TotalAmountDue.ToString("C");
}
private void btnPaymentButton_Click(object sender, EventArgs e)
{
amountDue = double.Parse(this.txtAmountDue.Text);
amountPaid = double.Parse(this.txtAmountPaid.Text);
Payment orderPaymentObject = new Payment(amountDue, amountPaid);
}
The data disappears because you're creating a temporary object at the method's scope, meaning it doesn't exist outside the method.
To fix that declare the data member at the class level and use it like so:
Payment m_orderPaymentObject = null;
private void btnPaymentButton_Click(object sender, EventArgs e)
{
amountDue = double.Parse(this.txtAmountDue.Text);
amountPaid = double.Parse(this.txtAmountPaid.Text);
m_orderPaymentObject = new Payment(amountDue, amountPaid);
}
Repeat the process for any other data object you need.
This is one way to do it.
class ClassName
{
// available anywhere within the class; remember to instantiate before referencing
private PizzaOrder _order;
private Payment _payment;
private void btnOrderButton_Click(object sender, EventArgs e)
{
numberOfPizzas = int.Parse(this.txtNumberOfPizzaOrdered.Text);
numberOfCokes = int.Parse(this.txtNumberOfCokesOrdered.Text);
_order = new PizzaOrder(numberOfPizzas, numberOfCokes);
this.txtAmountDue.Text = _order.TotalAmountDue.ToString("C");
}
private void btnPaymentButton_Click(object sender, EventArgs e)
{
amountDue = double.Parse(this.txtAmountDue.Text);
amountPaid = double.Parse(this.txtAmountPaid.Text);
_payment = new Payment(amountDue, amountPaid);
}
}
Related
Context: I have two windows: one is the main window in which I create a new button and add it to a StackPanel. My goal is to make a program that when you enter some data (like title, group and image) in another window these parameters go to the main window and are used to create the new button.
Code:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// Click event of the accept button
string tituloHabilidad = Convert.ToString(tituloBox.Text);
string grupoHabilidad = Convert.ToString(claseBox.Text);
int nivelHabilidad = Convert.ToInt32(nivelBox.Text);
this.tituloHabilidad = tituloHabilidad;
this.grupoHabilidad = grupoHabilidad;
this.nivelHabilidad = nivelHabilidad;
tituloBox.Text = "";
claseBox.Text = "";
nivelBox.Text = "";
//menu.crearBoton(tituloHabilidad, grupoHabilidad, nivelHabilidad, nuestroIcono);
this.Visibility = Visibility.Hidden;
}
private void bHabilidades_Copy_Click(object sender, RoutedEventArgs e)
{
//vent is the calling of the entering data window
vent.Show();
//The retorno methods are simply the getters for the parameters of the button
ImageBrush nuestroIcono = vent.retornoIcono();
string tituloHabilidad = vent.retornoTitulo();
string grupoHabilidad = vent.retornoGrupo();
int nivelHabilidad = vent.retornoNivel();
//This method below is the method that creates buttons. The parameters are the data introduced in the entering data button
crearBoton(tituloHabilidad, grupoHabilidad, nivelHabilidad, nuestroIcono);
}
//The crearBoton method adds it to the stackPanel
Problem: When I click the "accept" button that sets the data entering window to invisible and next I call the method that creates a new button (in main window) a blank button is created, and if I enter new data in the entering data window the new created button has effectively the correct data (but this data is the old one so it doesn't match the actual request)
What the solution should look like: I think I need an "if" conditional to run the create button method after the getting data method. However I accept whichever solution you make if the code works.
vent.Show()
doesn't block execution of thread, so without waiting for response it just proceeds to next line. You can change it like this :
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// Click event of the accept button
//string tituloHabilidad = Convert.ToString(tituloBox.Text);
//string grupoHabilidad = Convert.ToString(claseBox.Text);
//int nivelHabilidad = Convert.ToInt32(nivelBox.Text);
//this.tituloHabilidad = tituloHabilidad; // basically setting this.x = x; does nothing
//this.grupoHabilidad = grupoHabilidad;
//this.nivelHabilidad = nivelHabilidad;
//tituloBox.Text = "";
//claseBox.Text = "";
//nivelBox.Text = "";
//menu.crearBoton(tituloHabilidad, grupoHabilidad, nivelHabilidad, nuestroIcono);
this.DialogResult = true;
}
private void bHabilidades_Copy_Click(object sender, RoutedEventArgs e)
{
//vent is the calling of the entering data window
// Here is something you need to decide :
// 1. You create new vent dialog and show it, e.g.
// var vent = new YourWindowName(); // I recommend personally
// or 2. set dialogresult to null, but dialog will have prefilled data from before (if dialog was used previously)
// vent.DialogResult=null;
if(vent.ShowDialog() == true)
{
//The retorno methods are simply the getters for the parameters of the button
ImageBrush nuestroIcono = vent.retornoIcono();
string tituloHabilidad = vent.retornoTitulo();
string grupoHabilidad = vent.retornoGrupo();
int nivelHabilidad = vent.retornoNivel();
//This method below is the method that creates buttons. The parameters are the data introduced in the entering data button
crearBoton(tituloHabilidad, grupoHabilidad, nivelHabilidad, nuestroIcono);
}
}
//The crearBoton method adds it to the stackPanel
Essentially it would wait for dialog result to be true, and only then proceed to create button. If for example you have button cancel on enter info window
private void Button_Cancel_Click(object sender, RoutedEventArgs e)
{
// Click event of the cancel button
this.DialogResult=false;
}
then dialog would close, but no button would be created.
Edit : after some questions you have raised I know where the actual problem is.
Methods retornoIcono(), retornoTitulo() and retornoNivel() are most likely just returning tituloBox.Text,claseBox.Text and nivelBox.Text. Since you're setting their values in local variables and clearing textbox.text afterwards it was always giving you empty.string value (or ''). So to fix that there're few ways :
comment out the lines that are clearing textboxes (as I've done above, but that is bad practice even if it works);
create private variables in window/form class and adjust methods accordingly (or if you prefer - just set them to public and get rid of methods altogether), e.g.
Option 2 sample : private variables / public methods
public class YouWindowName
{
private string tituloHabilida, grupoHabilidad;
private int nivelHabilidad;
private void Button_Click_1(object sender, RoutedEventArgs e)
{
<...snip...>
tituloHabilidad = Convert.ToString(tituloBox.Text);
grupoHabilidad = Convert.ToString(claseBox.Text);
nivelHabilidad = Convert.ToInt32(nivelBox.Text);
<...snip...>
}
public string retornoTitulo()
{
return tituloHabilidad;
}
// do other analogically
My question is about dealing with multiple forms in C# Windows form application. I am developing a code for playing a movie and moving it frame by frame with buttons. I already have the code for moving the movie frame by frame with ctlcontrols in Windows Media Player.
The thing that I'm having an issue with is that I want to have a main form and a movie form, and when I click the button in the main form, I want to send a number to the other form and if the number was 2, I want the movie to go frame by frame in the movie form. And I want to do it without opening a new form every time I click the button. I have made a function in my second form and I called it in the button in the main form. It is expected to work but it doesn't.
The code for the button in the main form is:
private void button1_Click(object sender, EventArgs e)
{
value = txtSendNum.Text; // get the value from the textox and
// assign it to string variable
MovieForm movieform = new MovieForm(); //create an object for MovieForm
movieform.ConnectForms(value);
}
The code for the function(ConnectForms function) in the second form is:
public void ConnectForms(string value)
{
val = Convert.ToInt32(value);
if (val == 2)
{
axWindowsMediaPlayer1.Ctlcontrols.play();
axWindowsMediaPlayer1.Ctlcontrols.currentPosition += 0.5;
axWindowsMediaPlayer1.Ctlcontrols.stop();
}
}
You are creating a new MovieForm every time the user clicks the button, this is wrong. You need a reference to the MovieForm that was previously open.
This is the difference between the meaning of Object and Class. You need a reference to the object not a new object from the same class.
A simple way to make it work is like the following code:
MovieForm movieform = null;
private void button1_Click(object sender, EventArgs e)
{
value = txtSendNum.Text;
if(movieform == null || movieform.IsDisposed)
{
movieform = new MovieForm(); //create an object for MovieForm
movieform.Show();
movieform.ConnectForms(value);
}
else
{
movieform.ConnectForms(value);
movieform.Focus();
}
}
You must have a reference the the other form. Instead of declaring movieform as a local variable, declare it as a class level variable (i.e., a field)
private MovieForm _movieform = new MovieForm();
private void button1_Click(object sender, EventArgs e)
{
value = txtSendNum.Text; //get the value from the textox and assign it to string variable
_movieform.ConnectForms(value);
_movieform.Show();
}
A local variable, i.e., a variable declared in a method has a lifetime limited to one method call (I'm not talking about special cases like iterators and closures).
A class field has the same lifetime as the object (here the Form).
Instead of creating a method on each form that receives a value or passing the value as parameter on the constructor of each form, or creating a new property to set the value to search for it later you should use the Tag property of the Control that is already created for that. Here you is how it is used
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.tag?view=netframework-4.7.2
private void buttonNewCustomer_Click(object sender, EventArgs e)
{
/* Create a new customer form and assign a new
* Customer object to the Tag property. */
CustomerForm customerForm = new CustomerForm();
customerForm.Tag = new Customer();
customerForm.Show();
}
I have a datacontrol.cs(UserControl), which is contain textbox1 and codebehind window having a method with parameter of currentvalue
public void bindvalue(float currentvalue)
{
textbox1.Clear();
textbox1.Text = currentvalue.ToString();
}
I have a Form, Here added the usercontrol in this form and which contains a Button
So when clicking button it pass a currentvalue by the way of method to the datacontrol class like that .
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
}
Everything working fine to me. It pass the current value to the usercontrol class and there current value assigned/added to the textbox1.Text = currentvalue.ToString();. It doesn't shows any error . But finally the textbox doesn't shows any value.
I used breakpoint to check the functionality. It gave current value to the textbox. But strange!!!..
I can't predict whats wrong in my code.
Helps appreciated.:)
Your instance of datacontrol with required value (1500.00f) does not exist on your form. You are only delcaring it, passing value and forgetting about it.
If you have already added user control to form and want to call bindvalue method of existing control, you should do the following:
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
this.dataControl1.bindvalue(currentvalue);
}
Note that dataControl1 is the name of your user control on the form, it can be different from dataControl1.
If you want to create new user control and call bindvalue, you should add new instance on the form:
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
this.Controls.Add(obj);
}
If it is already dynamically added control on the form, declare a field of Form class, assign new instance of it control, when you want it, and call to it as it shows in the first example.
You need add instance of datacontrol to the form
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
Controls.Add(obj);
You can simply make a call to bindvalue method by using the tagename of your user control in button click event handler.
Suppose the tag name is 'datacontrol', then you should use the following lines of code to achieve your task:
protected void Button1_Click(object sender, EventArgs e)
{
float myvalue = 150.50f;
datacontrol1.BindValue(myvalue);
}
Regards, Aamir ( .Net developer)
Please marks this thread as answer if it solved what were looking for... thanks
And dammit, I'm getting frustrated. I'm doing my first mini-game, I think the name in english is Tic-Tac-Toe, and so, I have a main menu where I choose the option 2 players, then i get a inputbox asking for the 2 players names (i used a visual basic reference) and store it in 2 variables that i send to my constructor (?). I'm potuguese so I don't really know how you guys call it, but I'll show you the code.
So, in the first Form, I have:
private void doisJogadoresToolStripMenuItem_Click(object sender, EventArgs e)
{
jogadorTempUm = Microsoft.VisualBasic.Interaction.InputBox("Jogador 1");
jogadorTempDois = Microsoft.VisualBasic.Interaction.InputBox("Jogador 2");
jog = new DoisJogadores(jogadorTempUm, jogadorTempDois);
DoisJogadores novoDois = new DoisJogadores();
novoDois.ShowDialog();
}
That gets sent to the other Form:
public DoisJogadores(string teste1, string teste2)
{
jogador1 = teste1;
jogador2 = teste2;
}
And I save it in the class:
private string jogador1
private string jogador2
And the values get saved there. But I tried to place them in a textbox to show the players names and it just goes blank.
Anyone that can help me?
You are showing not that form which you are passing values to. Here is a fix
private void doisJogadoresToolStripMenuItem_Click(object sender, EventArgs e)
{
jogadorTempUm = Microsoft.VisualBasic.Interaction.InputBox("Jogador 1");
jogadorTempDois = Microsoft.VisualBasic.Interaction.InputBox("Jogador 2");
// pass values to form you are creating
DoisJogadores novoDois =
new DoisJogadores(jogadorTempUm, jogadorTempDois);
novoDois.ShowDialog();
}
Also make sure you are assigning jogador1 and jogador2 to textboxes. E.g. you can subscribe to form's load event in DoisJogadores form:
private void DoisJogadores_Load(object sender, EventArgs e)
{
textbox1.Text = jogador1;
textbox2.Text = jogador2;
}
I had a DataGrid and a ContextMenuStrip in it. When I click SelectMenuStrip in a row I want the ClickEvent of the context menu to get all data in that row in a databean class and return that databean class, so that I can fill the data in another class-
All was fine I defined event as below
private CustomerDataBean toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = null;
int rowno = tblcustomerdataview.CurrentCellAddress.Y;
custdatabean.Customerpk = int.Parse(tblcustomerdataview.Rows[rowno].Cells[0].Value.ToString());
custdatabean.Contactno = tblcustomerdataview.Rows[rowno].Cells[6].Value.ToString();
custdatabean.Emailid = tblcustomerdataview.Rows[rowno].Cells[7].Value.ToString();
custdatabean.Other = tblcustomerdataview.Rows[rowno].Cells[8].Value.ToString();
return custdatabean;
}
but in designer.cs I am getting an error in line:
this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click);
The error is:
Error 1:
'WindowsFormsApplication3.CustomerDataBean WindowsFormsApplication3.CustomerSearch.toolStripMenuItem1_Click(object, System.EventArgs)' has the wrong return type D:\WindowsFormsApplication3\WindowsFormsApplication3\Merchandising\customerSearch.Designer.cs 83 46 NFTRANS
Where have I done something wrong?
Let me explain the situation
I had a jobcodeform where user should input the customercode in combobox if he forget customercode he can use a buton to go to another form called customersearch where there is a datagrid table with a context menustrip which when clicked gets the whole details of the selected row in a customerdatabean and return that back to the first jobcodeform
Your code doesn't make a lot of sense. Click events don't return anything (except void), they really just run a procedure.
Your quick fix is to match the signature of the handler:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
// do something, don't return anything
}
What you need to define is what are you trying to do with your CustomerDataBean object. If you are just trying to add it to a list, then add it to a list:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = new CustomerDataBean();
// set properties
myBeans.Add(custdatabean);
}
The code you currently have doesn't even create a CustomerDataBean object. It's null, and then you are trying to update a null object. That isn't going to work.
Ask yourself where should your click event return the object to?
What code will process that bean?
The others have explained what is wrong with your click event.
Here's one possible method:
Have your click event call a separate method to process the bean. Something like this, perhaps:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = null;
int rowno = tblcustomerdataview.CurrentCellAddress.Y;
custdatabean.Customerpk = int.Parse(tblcustomerdataview.Rows[rowno].Cells[0].Value.ToString());
custdatabean.Contactno = tblcustomerdataview.Rows[rowno].Cells[6].Value.ToString();
custdatabean.Emailid = tblcustomerdataview.Rows[rowno].Cells[7].Value.ToString();
custdatabean.Other = tblcustomerdataview.Rows[rowno].Cells[8].Value.ToString();
processBean(custdatabean);
}
private void processBean(CustomerDataBean bean)
{
//Code to process the bean here.
}
ToolStripMenuItem click event handlers need to return void.