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()
{
//..
}
}
Related
I have seen a few links on attempts at this but I haven't found a solution. I am attempting to access my form textbox and update it with text from another class. I can update the text within my DataOrganizerForm class directly but when I pass text back to the DataOrganizerForm class then it doesn't update on the GUI. Here is what I have:
public partial class DataOrganizerForm : Form
{
//Default constructor
public DataOrganizerForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//Handle a Start/Stop button click
private void start_stop_button_Click(object sender, EventArgs e)
{
SerialNumberSearcher snsearch = new SerialNumberSearcher();
snsearch.searchSN();
}
//Allow simple access to update to notification textbox
public void setNotificationText(string text)
{
notification_textbox.Text = text;
}
}
public class SerialNumberSearcher
{
public void searchSN()
{
DataOrganizerForm formAccess = new DataOrganizerForm();
formAccess.setNotificationText("Updated text from different class");
}
}
Well, it won't update the textbox 'cause you're instantiating another object of the DataOrganizerForm class. What you could do is passing a reference of the form object to the SerialNumberSearcher, like this:
public class SerialNumberSearcher
{
private readonly DataOrganizerForm _form;
public SerialNumberSearcher(DataOrganizerForm form)
{
_form = form;
}
public void searchSN()
{
_form.setNotificationText("Updated text from different class");
}
}
You need to understand at which instance you operate. When you use the new-eperator you create a new instance, like a new copy of that type.
DataOrganizerForm formAccess = new DataOrganizerForm();
The original Form is a different instance then the one you create in the searchSN method.
You need to pass that instance into the method to manipulate it:
public void searchSN(DataOrganizerForm formAccess )
{
formAccess.setNotificationText("Updated text from different class");
}
When you want to call this method you need to use this to reference the current object :
private void start_stop_button_Click(object sender, EventArgs e)
{
SerialNumberSearcher snsearch = new SerialNumberSearcher();
snsearch.searchSN(this);
}
this will access the current instance of the Form, thereby allowing you to manipulate the textbox that you are interested in.
When do you use the “this” keyword? might also be helpfull
Thanks for the help. This is what I was able to do to make my application work. I passed the Textbox object by reference to my other class and was able to display my information that way. Also, I had issues getting my text box to continuously update. I had to add
public partial class DataOrganizerForm : Form
{
//Default constructor
public DataOrganizerForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//Handle a Start/Stop button click
private void start_stop_button_Click(object sender, EventArgs e)
{
SerialNumberSearcher snsearch = new SerialNumberSearcher();
snsearch.searchSN(notification_textbox);
}
//Allow simple access to update to notification textbox
public void setNotificationText(string text)
{
notification_textbox.Text = text;
notification_textbox.Update();
}
}
public class SerialNumberSearcher
{
public void searchSN(Textbox notifyTextbox)
{
notifyTextbox.setNotificationText = "Updated text from different class";
notifyTextbox.Update();
}
}
I hope that my question is relevant to be answered because I'm a newbie.
For example, I have two coding named with Class1.cs and Form1.cs. Basically, Class1.cs is the program where the process of image filtering is occured, meanwhile in Form1 is the program where I allow it to load an image from a file.
Is it possible for me to access Class1 from Form1 right after I click on the button to process it?
Class1.cs
public class Class1
{
public static class Class1Program
{
// My program for image filtering is starting here
}
}
Form1.cs
public partial class Form1 : Form
{
public Form1() => InitializeComponent();
private void LoadImageButton_Click(object sender, EventArgs e)
{
// My program here is to open up a file image right after I click on this button
}
private void ResultButton_Click(object sender, EventArgs e)
{
// Here is the part where I don't know how to access the program from "Class1.cs".
// I'm expecting the image that I've load before will be able to filter right after I clicked on this button
}
}
I'm wondering if there is a need to add or edit some program on the "Program.cs".
I'm hoping that my question can be answered. Thank you so much for your time.
Let me add one property and a method to the static class for make it understandable. Let the Class1Program looks like the following:
public static class Class1Program
{
public static int MyProperty{get; set;} // is a static Property
public static void DoSomething() // is a static method for performing the action
{
//my program for image filtering is starting at here
}
}
Now you can access the method and property inside the Form1 like this:
private void ResultButton_Click(object sender, EventArgs e)
{
Class1.Class1Program.MyProperty = 20; // assign 20 to MyProperty
int myint = Class1.Class1Program.MyProperty; // access value from MyProperty
Class1.Class1Program.DoSomething();// calling the method to perform the action
}
You can do one of these two things:
1.You can access data in Class1 by using static variables:
namespace MyProgram
{
class Class1
{
public static int Class1Variable;
}
}
namespace MyProgram
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void LoadImageButton_Click(object sender, EventArgs e)
{
//Load image logic
}
private void ResultButton_Click(object sender, EventArgs e)
{
Class1.Class1Variable = 1;
}
}
}
2.You can create an instance of Class1 inside Form1:
namespace MyProgram
{
class Class1
{
public int Class1Variable;
public Class1()
{
}
}
}
namespace MyProgram
{
public partial class Form1 : Form
{
public Class1 c1;
public Form1()
{
InitializeComponent();
c1 = new Class1();
}
private void LoadImageButton_Click(object sender, EventArgs e)
{
//Load image logic
}
private void ResultButton_Click(object sender, EventArgs e)
{
c1.Class1Variable = 1;
}
}
}
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.
Inside my Main method I'm instantiating the UpdateDialog class inside which based on if the user presses a button or not I need to call function1() from Main. Here is the code:
public partial class Main : Form
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
}
}
What should I do to be able to call function1() from Main inside the partial class UpdateDialog?
LE: although the method suggested by Styxxy seems right it doesn't work well in my app because of cross-thread invalid operation so I ended up using the delegate workaround suggested by Cuong Le.
You'll have to have an instance of the Main form in your UpdateDialog form. As you say that UpdateDialog is a child form of your Main form, I guess that you create the UpdateDialog in your Main form and do a show there. Before showing that form, you could assign the Parent property.
var updateDialog = new UpdateDialog();
// Or use "UpdateDialog updateDialog = new UpdateDialog();" as people like Andreas Johansson don't like the "var" keyword
// Do other stuff here as well
updateDialog.Parent = this;
// Or use Show() for non modal window
updateDialog.ShowDialog();
You get the error ArgumentException: Top-level control cannot be added to a control.. Now this can be solved in two ways.
You can set the TopLevel property to false on your Main form (I'm not a huge fan of this).
You can use the Owner property to your Main form (this). Below two ways of doing it.
You can set the Owner manually:
updateDialog.Owner = this;
Or you can add this as parameter to the Show(owner) or ShowDialog(owner) methods; this way, the Owner is also being set.
updateDialog.Show(this);
// or
updateDialog.ShowDialog(this);
"Full" code makes this:
var updateDialog = new UpdateDialog();
// Do other stuff here as well
updateDialog.Owner= this;
updateDialog.ShowDialog(); // or use .Show()
// or
updateDialog.ShowDialog(this); // or use .Show(this)
I suggest you create an event in UpdateDialog then subscribe it after you create an instance inside the Main class. This way you have a better separation between these 2 classes.
public partial class Main
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnButton2Click += OnUpdateDialogButton2Click;
update.ShowDialog();
}
void OnUpdateDialogButton2Click(object sender, EventArgs e)
{
function1();
}
}
public partial class UpdateDialog
{
public event EventHandler<EventArgs> OnButton2Click;
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
if (OnButton2Click != null)
{
this.OnButton2Click(this, e);
}
}
}
Pass Main class instance to your Update Form and store it in instance variable -
Main mainWindow = null;
public UpdateDialog(Main mainForm)
{
mainWindow = mainForm;
}
private void button2_Click(object sender, EventArgs e)
{
mainWindow.function1();
}
And from Main method -
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog(this);
update.ShowDialog();
}
You could turn it around, and let Main form listen to clicks from the UpdateDialog.
In Main:
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnSomethingClicked += function1;
update.ShowDialog();
}
void form_OnSomethingHappened(object sender, EventArgs e)
{
// Do the stuff you want
}
In UpdateDialog:
public event EventHandler OnSomethingHappened;
private void button2_Click(object sender, EventArgs e)
{
EventHandler handler = OnSomethingHappened;
if (handler != null) handler(this, e);
}
The ShowDialog() method returns a DialogResult you can call function1 one of after the dialog is closed.
http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx
Can pass the Main class like a reference.
For example:
public partial class Main : Form
{
//make it internal, if UpdateDialog in the same assembly, and it only one that would use it. In other words hide it for outside world.
internal void function1()
{
doing_stuff_here();
}
....
}
public partial class UpdateDialog : Form
{
private MainForm _main = null;
public UpdateDialog (MainForm main) { //Accept only MainForm type, _not_ just a Form
_main = main;
}
private void button2_Click(object sender, EventArgs e)
{
_main.function1(); //CALL
}
}
Something like this. You can change this accroding to your precise requirements, but this is a general idea.
Approach #1
You need to create an instance of class Main.
Main foo = new Main();
foo.function1();
Approach #2
You need to declare the method as static.
public static function1(){ ... }
....
Main.function1();
You can make your function1 a Partial method and this way you can use it in all your partial classes.
Partial methods allow the definition of a method to be located in one file and the body of the method to be optionally defined in another file. They can only be used in partial classes and were introduced as language features in C# 3.0 and Visual Basic 9.0, the versions that shipped with the .NET Framework 3.5 and Visual Studio 2008.
So what you can do is modify like this
public partial class Main : Form
{
public partial void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
public partial void function1();
private void button2_Click(object sender, EventArgs e)
{
function1();
}
}
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.