Updating GUI form Separate Class - c#

so I've been searching for the past few hours, reading on everything about how to update the GUI of the form from another class. I tried, backgroundworker, and Invoke, but nothing seems to work, or rather I'm not doing it right. (I'm still pretty new to c#) So..why doesn't this method work at all?
Form 1:
private void button2_Click_1(object sender, EventArgs e)
{
prog.stuff();
}
public void Updateprogressbar(int input)
{
progressBar1.Value = input;
}
Class Prog
public static void stuff()
{
Form1 f = new Form1();
int up = 100;
f.Updateprogressbar(up);
}
I know this is probably a very easy question, but I still can't figure it out. The progress-bar just won't update. And I do have it all enabled to public in the properties. Thanks anyway.

private void button2_Click_1(object sender, EventArgs e)
{
prog.stuff(this);
}
public void Updateprogressbar(int input)
{
progressBar1.Value = input;
}
public static void stuff(Form f)
{
int up = 100;
f.Updateprogressbar(up);
}
So you can see the reason your code doesn't work is because your instantiating a new instance of Form1 thats only alive in the stuff() method. In my code I pass a reference of Form1 into class Prog.Stuff there by giving me access to form1's methods.

Related

access backgroundworker from a public method

So i have form1 which has backgroundworker (dragged and dropped via design view).
I can get it to work in the places i need, however I need to call it from a public method.
In this public method
Utility.initpacks(object sender, EventArgs e,string formname)
SO my DoWork is in Form1.
I the public utility within the form do do a bunch of things, then THAT function needs to use the background worker inside Form1 again!
I could just copy the public method and put in the place of the method reference and all is well.. but that defeats the purpose of a public method doesn't it!?
Any ideas would be great thanks :)
EDIT:
SO my current setup (without a bunch of stuff not important):
public partial class frmimportinstitutions : Form
{
private void btnNext_Click(object sender, EventArgs e)
{
Utility.initpacks(sender, e, this.FindForm().Name);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Do stuff
}
}
public static class Utility
{
public static void initpacks(object sender, EventArgs e,string formname)
{
//I WANT TO USE THE BACKGROUND WORKER HERE
//Do a public method
//I want to stop the background worker here
}
}
Update (basd on comments):
Michael comments just mentioned to put the background worker starting in a public method:
public void startplash(string starttext)
{
if (!backgroundWorker1.IsBusy)
{
splashtext = starttext;
backgroundWorker1.RunWorkerAsync();
}
}
Now i want to call this method from the other method. In order to do this, the other method (init packs) needs to know where this method is doesnt it.
EG.
form1.startsplash("hello world")
So now i just need to send Form1 info to init packs...
Would this be ok:
Initpacks(Form Owner)
{
Owner.startsplash("hello world")
}
Another update!
Thanks for Michael we so far have this:
public static class Utility
{
public static void RunWorkerOfForm1()
{
var target = (Form1)Application.OpenForms.OfType<Form1>().FirstOrDefault();
target?.RunWorker();
}
}
Now I need to get this to work with different forms.. I havent tried the below but this is what i am going to try next.. correct me if i am wrong:
public static class Utility
{
public static void RunWorkerOfForm1(Form owner)
{
var target = (owner)Application.OpenForms.OfType<owner>().FirstOrDefault();
target?.RunWorker();
}
}
Final Answer (as per the ticked answer) - but using my code:
public partial class frmholidaypacks : Form, IWorker
{
private void btnextrapacks_Click(object sender, EventArgs e)
{
Utility.futurepacks<frmholidaypacks>(sender, e, pxid);
}
}
public interface IWorker
{
void startplash(string starttext);
}
public void startplash(string starttext)
{
if (!backgroundWorker1.IsBusy)
{
splashtext = starttext;
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Doing work. Using Splashtext string.
}
public static void futurepacks<T>(object sender, EventArgs e, int pxid) where T : IWorker
{
var target = (T)Application.OpenForms.OfType<T>().FirstOrDefault();
target?.startplash("Creating future packs");
}
100% Credit goes to Michael for working on this with me!
EDITED!
Ok, now I got it. Every form you want to run have to implement the IWorker interface. Then you pass the concrete Form to use as a generic parameter to the RunWorker function. The where clause only allows implementations of the IWorker interface - its (currently) not restricted to Form-instances.
public partial class Form2 : Form, IWorker
{
public Form2()
{
InitializeComponent();
}
public void RunWorker()
{
if (backgroundWorker1.IsBusy) return;
backgroundWorker1.RunWorkerAsync();
}
private void button1_Click(object sender, EventArgs e)
{
UtilityX.RunWorker<Form2>();
}
}
public static class UtilityX
{
public static void RunWorker<T>() where T : IWorker
{
var target = (T)Application.OpenForms.OfType<T>().FirstOrDefault();
target?.RunWorker();
}
}
public interface IWorker
{
void RunWorker();
}
Have you tried to use a static method,
you can put your code in a static method if you want too use it from multiple places.
public class MyClass
{
public static void MyMethod()
{
//..
}
}

Most efficient way to solve this circular reference?

New to C# here. So I got my first class (Form1) and second class (Class1) in different projects. I added Form1 to Class1's references because Form1 had data from its GUI that Class1 needed to make computations from its method. Problem is, I cant get the results from the method in Class1 to Form1 because I can't reference it because of circular reference.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void label3_Click(object sender, EventArgs e)
{
}
public void button1_Click(object sender, EventArgs e)
{
// for getting data from Class1
// ClassLibrary1.Class1 c = new ClassLibrary1.Class1();
// label7.Text = c.GetDate(); }
private void button2_Click(object sender, EventArgs e)
{
}
}
public class Class1
{
private int daysz;
private int GetDate()
{
Activity3_Espiritu.Form1 f = new Activity3_Espiritu.Form1();
daysz = (f.lastDay - f.firstDay).Days;
return daysz;
}
}
What's a clean way to get around this? I've tried interfaces but I've absolutely no idea how to use it, even after looking online for solutions.
Class1 should never need a reference to your Form1, instead the code from Form1 should call the GetDate() method in Class1 and pass in the appropriate parameters for GetDate() to evaluate. When GetDate() returns the result you simply assign it to a variable or back into the user control that needs to show it (would that be Label7?).
public void button1_Click(object sender, EventArgs e)
{
var c = new Class1();
var yourResult = c.GetDate(lastDay, firstDay);
label7.Text = yourResult;
}
public int GetDate(DateTime lastDate, DateTime firstDate)
{
return (lastDate - firstDate).Days;
}
If you can change signature of GetDate method you can try this code:
public class Class1
{
private int daysz;
private int GetDate(__yourDatType__ lastDay, __yourDatType__ firstDay)
{
daysz = (lastDay - firstDay).Days;
return daysz;
}
}
now, in button1_Click write this:
ClassLibrary1.Class1 c = new ClassLibrary1.Class1();
label7.Text = c.GetDate(this.lastDay, this.firstDay);

Changing WinForm element from outside its class

I have a simple Windows Form with a button and textbox. I want the textbox to update with some string when the button is pressed. I know the following works:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.text = "some string";
}
}
I also know, that the following will work. This gives me a bit more freedom, cause I can easily decide what I want to appear in the textbox:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
updateText("some string");
}
public void updateText(string s)
{
textBox1.Text = s;
}
}
Now, let's say that my code is getting big, and I want to keep things tidy. I want to move my code that performs updates into a different class called Updates. In that class I want to have a method that I can run on any textBox with any string. When I try the following, I get an error: The name 'textBox1' does not exist in the current context.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Updates.updateText("some string");
}
}
public class Updates
{
public void updateText(string s)
{
textBox1.Text = s;
}
}
I have seen more complex questions here about similar things, but I can't get their solutions to work. I think I'm missing something basic.
Additionally, I don't know how I would expand this method to accept any textBox, e.g.:
public void updateText(??? target, string s)
{
target.Text = s;
}
What type would target take?
Change your function to accept TextBox like this:
public void updateText(TextBox target, string s)
{
target.Text = s;
}
Samvel Petrosov answer is best solution, but if you would like to have another option, there it is: set the text box modifier to public (or internal), add reference to your form in Updates class. Then you will be able to modify it (text box) freely.

C# Trying to access textbox on form through a new class

Still in the process of learning C#, but I'm a bit confused on something here.
For example, I have a textbox on my form and it has the name of testTXT. Based on the code below, I've created a new class outside of the public partial one that's there by default, and now I'm trying to access testTXT but I cannot. I'm going to also need to access several other textboxes and things later on as well.
Here's a snippet of the code I'm working with thus far:
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass();
gc.CreatePackage("C:\\Users\\user\\Downloads\\output.docx");
}
private void browseButton_Click(object sender, EventArgs e)
{
var fsd = new FolderSelect.FolderSelectDialog();
fsd.Title = "Select folder to save document";
fsd.InitialDirectory = #"c:\";
if (fsd.ShowDialog(IntPtr.Zero))
{
testTXT.Text = fsd.FileName;
}
}
}
public class GeneratedClass
{
**trying to access testTXT right here, but can't.**
}
}
Any help would be greatly appreciated.
You could do this (see other answers), but you really shouldn't.
Nobody but the containing form has to know about the textboxes in it. Who knows, they might disappear, have their name changed, etc. And your GeneratedClass could become a utility class used by lots of forms.
The appropriate way of doing this, is to pass whatever you need from your textbox to your class, like so:
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass();
gc.CreatePackage(this.testTxt.Text);
}
public class GeneratedClass
{
public void CreatePackage(string name) { // DoStuff! }
}
This is because you have your TextBox type defined in Form1 class as private member. Thus can't be access with another class instance
Your question has little to do with C#, more to do with Object Oriented Concepts.
Instance of TextBox has to be given to 'GeneratedClass' somehow.
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void testButton_Click(object sender, EventArgs e)
{
GeneratedClass gc = new GeneratedClass(testTXT);
gc.DoSomething();
gc.CreatePackage("C:\\Users\\user\\Downloads\\output.docx");
}
private void browseButton_Click(object sender, EventArgs e)
{
var fsd = new FolderSelect.FolderSelectDialog();
fsd.Title = "Select folder to save document";
fsd.InitialDirectory = #"c:\";
if (fsd.ShowDialog(IntPtr.Zero))
{
testTXT.Text = fsd.FileName;
}
}
}
public class GeneratedClass
{
TextBox _txt;
public GeneratedClass(TextBox txt)
{
_txt= txt;
}
public void DoSomething()
{
txt.Text = "Changed the text";
}
}
}
You must make testTXT public.
See Protection level (Modifiers) of controls change automaticlly in .Net.
And access to TextBox as
public class GeneratedClass
{
GeneratedClass(Form1 form)
{
form.testTXT.Text = "1";
}
}

Clone form design and code with button

i have a really simple counter application, I made in C#.
Now what i want to know is it possible to clone the form design and code, so there are 2 counter's instead of one. with a button.
they both have to be working.
i'm an beginner.. so that's why i ask if this is possible.
So from this (this is what i currently have, without clone button):
http://i.stack.imgur.com/ASMY4.jpg
to this:
http://i.stack.imgur.com/acluZ.jpg
this is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void counteradd()
{
int current1 = Convert.ToInt32(totaltb.Text);
current1++;
totaltb.Text = Convert.ToString(current1);
}
public void counterreduce()
{
int current2 = Convert.ToInt32(totaltb.Text);
current2--;
totaltb.Text = Convert.ToString(current2);
}
public void counterreset()
{
totaltb.Text = ("0");
}
private void reducebttn_Click(object sender, EventArgs e)
{
counterreduce();
}
private void resetbttn_Click(object sender, EventArgs e)
{
counterreset();
}
private void addbttn_Click(object sender, EventArgs e)
{
counteradd();
}
}
Simply duplicating the controls and laying them out on the form will result in messy code. The "clone' that you are referring to would be to build the functional piece as a user-control, and then add that as a control to your form.

Categories