I have two classes, Form1.cs and secondclass.cs, I'm trying to do something on secondclass.cs and send the progress to a progress bar on Form1.cs , this is my current code:
Form1.cs
namespace DifferentClasses
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
secondclass.updateBar(20);
}
private void button2_Click(object sender, EventArgs e)
{
this.setBar(20);
}
public void setBar(int percentage)
{
this.progressBar1.Value += percentage;
Console.WriteLine(Convert.ToString(percentage));
}
}
}
secondclass.cs
namespace DifferentClasses
{
class secondclass
{
public static void updateBar(int percentage)
{
var frm = new Form1();
frm.setBar(percentage);
}
}
}
(this was a new project to test what I actually want in my main program)
as you see I have created 2 buttons, the first one runs the command via secondclass.cs
and the second one runs it directly from the same class. Funny enough both don't give errors
and both return the console line, however the first button doesn't actually change the progress bar and I can't figure out why.
The problem is in updateBar you are creating a new Form1 and setting the percentage on that.
The simplest way to solve this is to pass a reference to the current form into updateBar like this:
public static void updateBar(int percentage,Form1 f)
{
f.setBar(percentage);
}
and in the calling code do this:
secondclass.updateBar(20,this);
I'm guess the secondclass will end up running something which may take some time, so you may want to look at the async features in C#
Related
I'm trying to call a non-static method (LoadingListBox) in my class (ListDisplay) from a button click event in my AddTask class.
namespace Project
{
public partial class ListDisplay : Form
{
public void LoadingListBox()
{
//code
}
}
}
namespace Project
{
public partial class AddTask : Form
{
private void btnSubmit_Click(object sender, EventArgs e)
{
//code
//I want to call LoadingListBox here
}
}
}
I have tried creating an instance of ListDisplay by doing ListDisplay listDisplayI = new ListDisplay(); and then writing ListDisplay.LoadingListBox();
There were no errors with this code but when debugging the flow of control wouldn't go to the method it just carried on past it.
I have also tried doing what the answer suggests from this question:
Call a public method of main class from another class
But that comes up with an error as I can't overload the btnSubmit_Click method as the Designer freaked out. So I created a new method that had all of the code of btnSubmit_Click called public static void addingTask(ListDisplay) but I then had to create an instance of ListDisplay in order to put it as an argument in the btnSubmit_Click method hence ending up with two instances which is not what I want (due to answer of question).
So now I have come up with nothing and would appreciate any help you could give in order to call this LoadingListBox method.
Thanks!
Your two choices are based on whether or not you want a new instance of ListDisplay when you click the button or not.
Option 1:
namespace Project
{
public partial class AddTask : Form
{
private void btnSubmit_Click(object sender, EventArgs e)
{
var ld = new ListDisplay();
ld.Show();
ld.LoadingListBox();
}
}
}
Option 2:
namespace Project
{
public partial class AddTask : Form
{
private ListDisplay _ld;
public AddTask(ListDisplay ld)
{
_ld = ld;
}
private void btnSubmit_Click(object sender, EventArgs e)
{
_ld.LoadingListBox();
}
}
}
I have this MainForm class:
namespace homework_001{
public partial class MainForm : Form
{
public MainForm()
{InitializeComponent();}
public string Change
{
get{ return label.Text;}
set{ label.Text = value;}
}
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test();
a.changer();
}
}}
And I have this class:
namespace homework_001{
public class Test
{
private MainForm form = new MainForm ();
public void changer(){
form.Change = "qqqqq!";
}
}}
Desired workflow is to change the label/text on button press.
It compiles, but nothing happens after I press the button.
What might be the issue?
What is happening is that the form you are showing is not the same as the one inside the class Test.
To make things work you should pass the form to the class Test in this way:
public class Test
{
private MainForm form;
public Test(MainForm f)
{
this.form=f;
}
public void changer(){
form.Change = "qqqqq!";
}
}}
and in your main form you do this:
public partial class MainForm : Form
{
public MainForm()
{InitializeComponent();}
public string Change
{
get{ return label.Text;}
set{ label.Text = value;}
}
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test(this);
a.changer();
}
}}
done create a new object of the main form.. Instead. make the string Change public and static
and change it from test class like Mainform.Change="some text";
You're creating another MainForm object, different from the one that's actually displayed on the screen. To work on the same object you need to pass it to the Test class, like this:
Test a = new Test(this); // "this" is the MainForm object you want to work with
a.changer();
This will give Test class a reference to your MainForm object.
Now, you need to create a constructor in Test with one argument, and store the received reference to your form object in Test's private MainForm form field. You shouldn't have any trouble doing that.
change you code below:
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test();
a.changer(ref this);
}
you pass the form object to function by refrence and changed that
public class Test
{
public void changer(ref MainForm form){
form.Change = "qqqqq!";
}
}
refer this link Passing Reference-Type Parameters (C# Programming Guide)
Ok so I have six variables in one form that all change when various methods are invoked via buttons.
In another form I have six corresponding labels. I want to take the variables from the first form and set the SomeLabel.text in the second form when the button on the first form is pressed.
I've been trying to do this in this fashion Name=Mainform.InitializeComponent.SomeLabel.Text; but that doesn't work. I know the InitializeComponent method is private. I've tried changing it to public but that didn't prove fruitful either(also not good coding). So I came here to ask how I would do this. I was thinking about using a get and set setup but I'm still unable to access the label from the first form. I didn't include my code because nothing is broken in it and all the pieces that are needed are in the post.
You can either share a variable using public/internal Method or using `public / internal properties'
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Form2 frm = new Form2();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
frm.Show();
}
private void button1_Click(object sender, EventArgs e)
{
frm.SetTextLabel1("Hello world");
//or
frm.Label1Text = "HEllo world again";
}
}
}
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
//using method to set the value of label
public void SetTextLabel1(string value)
{
label1.Text = value;
}
//using property to set the value of label
public string Label1Text
{
set { label1.Text = value; }
}
}
}
Set Modifier property of label to Public. So you can access to label from Form object.
Well there's the quick and dirty way which you've already been provided. Or there's write a class to hold this common data ,add a method to call from form1's button that fires an event, that form2 subscribes to, reads the data and updates it's labels. They both know about the intermediate class but neither needs to know anything about the other.
Why don't you take those six variables as Public static in form2.
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Form2.VariableLable1 = "a";
Form2.VariableLable2 = "b";
}
}
public partial class Form2 : Form
{
public static string VariableLable1,VariableLable2;
private void form_load(object sender, EventArgs e)
{
Lable1.Text = VariableLable1;
Lable1.Text = VariableLable2;
}
}
I've stomped with a problem I've spent some hours trying to solve, with my very limited knowledge.
I have a listview in my form1 called listMachine
And I have a method in form1.cs such as
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.Show();
}
machinename.cs is another form, and I use that method to open my other form, with an object called open.
the machinename button is a simple form which just serves as an input receiver, it asks a name, we have to type it into the textbox, press a button and it receives the input.
This is the code that runs when you press the button
public void buttonAceitarnome_Click(object sender, EventArgs e)
{
if (textBoxnomenova.TextLength == 0)
{
toolTipEmptyname.Show("O nome da máquina não pode estar vazio", textBoxnomenova);
}
else
{
Variables.var = textBoxnomenova.Text;
//MessageBox.Show(Variables.var); debug purpose, the messagebox does carry variables.var text
obj.listMachine.Items.Add(Variables.var); //If I change the variables.var to "test" it will NOT add the item.
this.Close();
}
}
Also, I forgot to mention my Variables.cs class, I created it because it was the only way I found to pass variables from a class to another (machinename.cs to form1.cs), but still, the items are not added into the listview.
This is my variables.cs code
public static class Variables
{
public static string var;
}
The comments I added to the code also give you some extra debug info..
I didn't want to ask for online help, but couldn't solve this on my own :(
If I were you, I would first remove the Variables class.
Then, you'r first form/class is called obj.cs, am I right? Or is it form1.cs?
I made it look like this:
public partial class obj : Form
{
public static string text; //This is a variable that can be reached from
public obj()
{
InitializeComponent();
}
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.ShowDialog(); //I put ShowDialog instead of Show
addItem(); //This method is called when the showed dialog is closed (machinename.cs)
}
private void addItem()
{
listMachine.Items.Add(text);
}
}
and the machinename.cs class like this:
public partial class machinename : Form
{
public machinename()
{
InitializeComponent();
}
private void buttonAceitarnome_Click(object sender, EventArgs e) //This one can be private
{
if (textBoxnomenova.TextLength == 0)
{
//Something here
}
else
{
obj.text = textBoxnomenova.Text; //Initializing the public static variable
this.Close(); //Closes the form, next step will be to run the method in obj.cs
}
}
}
If I understood your question correctly, you wanted to add an item to the ListView called "listMachine" via a button in the form "machinename.cs". This code will do that. I hope it helps you.
Change the click event from private to protected.
protected void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
I have a program that has a parent form which then creates a child form. Upon clicking the updateButton within the child form, I want the searchButton within the parent form to fire.
However I get an error for protection reasons. I have tried setting everything Public just to see, still wont work for me.
Error 1 'SalesSystem.SystemForm.searchButton' is inaccessible due to
its protection level SalesSystem\UpdateForm.cs 111 20 SalesSystem
This is what I have so far.
Parent Code
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
Child Code
namespace SalesSystem
{
public partial class UpdateForm : Form
{
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
SystemForm parent = (SystemForm)this.Owner;
parent.searchButton.PerformClick();
this.Close();
}
}
}
Your searchButton button control is set to private by default in WinForm. You've said you set everything to public but I assume you mean you've set everything in the code you've posted to public. There are a few ways to fix this. The direct fix would be to simply go to Visual Studio designer, select the button, and set its Modifier property to internal or public.
However, it seems you're closing your form straight after so I'd just have my parent form subscribe to the FormClosing event of the form.
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.FormClosing += (s, o) =>
{
//your code for what the parent class should do
};
upForm.ShowDialog(this);
If you're not closing the form then you can create your own event handler that your parent form subscribes to.
You have 2 options:
create a public void search() method in your parent form. Then, instead of accessing the the button on the parent form and invoking its click event, you run the search code directly. The new method is not tied to a GUI element and accessing it from a different form is no problem.
The better solution is to create a delegate. A delegate is an execution target that will be assigned at run time. The parent form still has a public void search() method. And when it creates the child form, it will pass the name of that function as parameter. The child form has no knowledge about the parent form (as opposed to the first option where the child MUST know that there is a method called search()). When it is time to inform whoever created the child form, the delegate is called. This is a small example:
public partial class SystemForm : Form
{
public delegate void dSearch();
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
search();
}
private void search()
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname, search);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
And the child form:
public partial class UpdateForm : Form
{
private SystemForm.dSearch _target;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname, SystemForm.dSearch target)
{
_target = target;
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
_target();
this.Close();
}
}
You should use the "Model View Controller" or "Model View Presenter" pattern to approach this kind of thing.
Each form should only be concerned with displaying its contents to the user. When it comes to responding to UI events such as button clicks, each form (i.e. each "View") should simply raise an event which informs the controller/presenter that something has happened.
The controller/presenter should then respond appropriately. Then the logic that wires together different forms (such as the parent and child forms in your example) is encapsulated in the Controller class. Such logic does not really belong in either of the forms.
I wrote an example that demonstrates a simple design to do this sort of thing in another answer some time ago. Rather than copy/paste it all here, I'll just give you a link to it:
How to make Form1 label.text change when checkbox on form2 is checked?
You'll have to scroll down to see my answer. It's broadly similar to what you're doing; hopefully it will make sense to you! Follow the instructions to make a test application and run it to see what happens.
I'm tired and might be missing something but that is correct behaviour.
Your child form does not directly inherit from your parent form.
Your parent form has a protected level, so only it and classes that extend it can access the method.
2 solutions:
Change your child form to:
public partial class UpdateForm : SystemForm
Change method to public
public void searchButton_Click(object sender, EventArgs e)
You could expose a Search Event from your UpdateForm and subscribe to this event in the SystemForm
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.OnSearch += Search;
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
private void Search(string searchParameter)
{
....
}
}
namespace SalesSystem
{
public delegate void SearchEventHandler(string searchParameter);
public partial class UpdateForm : Form
{
public event SearchEventHandler OnSearch;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
OnSearch("SearchThis");
this.Close();
}
}
}