简体   繁体   中英

Giving other classes control of a Windows Form Object

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?

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

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM