我正在寻找从另一个类控制Windows窗体对象的最佳方法。 请不要回答,如果您的答案是“这不是您在OOP语言中的方式!”。 请注意我需要的东西:
我的Windows窗体中有一个看不见的进度条。如果我按下Windows窗体上的按钮,应该加载一个文件,进度条应该执行一些步骤...... 由于文件加载操作非常复杂,我从一个自己的类加载它,该类用于某种类型的文件。 像:
void TestButton_Click(object sender, EventArgs e)
{
MapFiles.ProcessFile()
}
现在在ProcessFile方法中,我想控制我的表单中的ProgressBar。 如果我将ProgessBar设为公共和静态,它就可以工作。但这有一些不满。您无法再控制“表单设计器”中的元素。
如果我只能访问我的Form的实例对象,那将很容易。但是我不知道自从表单初始化后如何:
Application.Run(new Form1());
我不想在这里继续做一些事情,因为MapFiles与Form1没有任何关系......
是否有另一种/最佳方法从另一个类中控制此ProgressBar?
答案 0 :(得分:1)
为什么不直接将进度条的引用传递到ProcessFile
方法:
MapFiles.ProcessFile(progressBar1);
然后您可以从班级访问它,例如:
ProcessFile(ProgressBar progressBar1)
{
progressBar1.Value = 0;
}
注意:正如您所说,这可能不是最佳方式。但是你已经明确了你的具体要求,所以这是我的建议,让你的班级控制进度条
答案 1 :(得分:0)
如果您不想绕过传递表单的引用,可以制作类似的内容。
public static class FormSharer
{
public static YourFormClass Form {get; set;}
}
在你的表单加载事件中
FormSharer.Form = this;
并且您可以从其他所有类中引用FormSharer.Form
话虽如此,这样做并不是一个好主意。但是你又需要它,就是这样。
答案 2 :(得分:0)
只要您在同一个项目中的课程可以这样做:
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);
}
}
我更新了我的答案,因此您无需公开控制
答案 3 :(得分:0)
您可以使用Progress
类来非常有效地处理此问题。
刚开始在点击处理程序中定义一个Progress
对象,在该对象中指示如何更新进度;在这种情况下,通过更新进度条的值。
然后将Progress
实例*as an
IProgress`实例*传递给您的工作人员。
然后,工作人员可以使用Report
来表示进度。
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
}
});
}
最重要的是Progress
类甚至捕获当前SynchronizationContext
并在调用progress改变事件时使用它,因此即使您调用{{{{}}也可以在UI线程中触发该事件1}}来自其他一些帖子。