Reputation: 3208
I´m searching for the best way to control an object of my Windows Form, from another Class. Pls don´t answer, if your answer is "This is not the way you do it in OOP Languages!". Pls take care of what I need:
I have a invisible Progress Bar in my Windows Form. If I press a button on my Windows Form, a file should be loaded and the Progress Bar should perform some steps... As the file loading operation is pretty complex, I load it from an own class which is for files of a certain type. Like:
void TestButton_Click(object sender, EventArgs e)
{
MapFiles.ProcessFile()
}
Now in the ProcessFile method I want to take control to the ProgressBar in my Form. It works, if I make the ProgessBar public and static. But this has some grievances. You can´t control the element in the Form Designer anymore.
It would be easy, if I could just access a instanced object of my Form. But I don´t know how since the form is initialized with:
Application.Run(new Form1());
I didn't wanna do something with Inheritance here, because the MapFiles do not really have anything to do with the Form1...
Is there another / the best way to take control over this ProgressBar from another Class?
Upvotes: 0
Views: 604
Reputation: 203842
You can use the Progress
class to handle this very effectively.
Just start out defining a Progress
object in your click handler in which it indicates how to update progress; in this case, by updating the value of the progress bar.
Then pass that Progress
instance*as an
IProgress` instance* to your worker.
The worker can then use Report
to indicate progress.
private void button1_Click(object sender, EventArgs e)
{
Progress<int> progress = new Progress<int>(
percent => progressbar1.Value = percent);
DoStuff(progress);
}
private void DoStuff(IProgress<int> progress)
{
Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
progress.Report(i);
Thread.Sleep(200); //placeholder for real work
}
});
}
Best of all the Progress
class even captures the current SynchronizationContext
and uses that when invoking the progress changed event, so the event will be able to fire in the UI thread even if you call Report
from some other thread.
Upvotes: 0
Reputation: 458
for as long as your class in the same project you can do this:
public class Class1
{
public void AccessForm()
{
var thatForm = (Form1)Form.ActiveForm;
var progressBar = thatForm.Controls.Cast<Control>().Where(a => a.Name =="progressBar1").FirstOrDefault();
MessageBox.Show(progressBar.Name);
}
}
I updated my answer so you do not have to make any control public
Upvotes: 0
Reputation: 2381
If you don't want to go around passing references to your form you can make something like this.
public static class FormSharer
{
public static YourFormClass Form {get; set;}
}
in your form load event you do
FormSharer.Form = this;
and from every other class you just reference FormSharer.Form
That being said, its not a very good idea to do this. But then again you need it so that's that.
Upvotes: 0
Reputation: 48465
Why don't you just pass a reference to the progress bar into your ProcessFile
method:
MapFiles.ProcessFile(progressBar1);
Then you can access it from your class, for example:
ProcessFile(ProgressBar progressBar1)
{
progressBar1.Value = 0;
}
NOTE: As you have said, this probably isn't the best way. But you have made your specific requirements clear so this is my suggestion to give your class control over the progress bar
Upvotes: 1