简体   繁体   English

c#如何从其他类更改/访问WinForms控件

[英]c# How to change/access WinForms controls from a different class

So I'm trying to change the text from a WinForms project, from another class than the Form class. 因此,我试图从WinForms项目,而不是Form类之外的其他类更改文本。 It should work like this: 它应该像这样工作:

对

But instead it does this: 而是这样做:

错误

The way I used to do it is pass along the object as a parameter to my other class and from that other class I could change the text. 我过去的做法是将对象作为参数传递给另一个类,然后可以从另一个类更改文本。 I do the same with the progressbar and it does work there, so it's weird that it works with the progressbar but not the label. 我在进度条上也做同样的事情,并且确实在那儿工作,所以奇怪的是,它与进度条一起工作,但不适用于标签。

I use this method to change the progressbar: 我使用这种方法来更改进度栏:

public void IncreaseProgress(int progBarStepSize, String statusMsg, int currentProject=-1) {
   if (currentProject != -1) {
      lblStatus.Text = String.Format("Status: {0} | project {1} of {2}",statusMsg,currentProject,ProjectCount);
   }
   else {
      lblStatus.Text = String.Format("Status: {0}",statusMsg);
   }

   pb.Increment(progBarStepSize);
}

And here is where I use the method: 这是我使用方法的地方:

public void InitialiseFile(List<string> filePaths, int eurojobType)
{
    foreach (string sheet in outputSheets) {
        switch (sheet) {
            case "Summary":
                for (int i = 0; i < filePaths.Count; i++) {
                            var filePath = filePaths[i];
                    IncreaseProgress(1, "Reading Summary", i);
                    worksheetIn = excelReader.ReadExcelSummary(filePath);

                    IncreaseProgress(1, "Writing Summary", i);
                    excelWriter.WriteExcelSummary(worksheetIn);
                }
                break;
            case "Monthly_Cat1":
                for (int i = 0; i < filePaths.Count; i++) {
                    var filePath = filePaths[i];
                    IncreaseProgress(1, "Reading Monthly", i);
                    worksheetIn = excelReader.ReadExcelMonthly(filePath);

                    IncreaseProgress(1, "Writing Monthly", i);
                    excelWriter.WriteExcelMonthly(worksheetIn);
                }
                break;
        }
    }
    IncreaseProgress(1, "Completed!");
}

Now I know this code works because the progressbar increments. 现在我知道此代码有效,因为进度条会增加。 And it should jump in the first if-loop because i gets passed as a parameter, which is never -1 . 而且它应该在第一个if循环中跳转,因为i被作为参数传递了,永远不会为-1

//manager class
private Label lblStatus;
private ProgressBar pb;

public Manager(ProgressBar pb, Label lbl){
    this.pb = pb;
    lblStatus = lbl;
}

//Form class
Manager mgr = new Manager(progressBar1, lblStatus, projectFilePaths.Count, outputSheets.ToArray(), exportPath);
mgr.InitialiseFile(projectFilePaths, eurjobType);

You can call lblStatus.Refresh(); 您可以调用lblStatus.Refresh(); to force the control to be redrawn, after setting its Text . 在设置其Text后,强制重新绘制控件。 But consider Slaks comment: 但是考虑一下Slaks的评论:

Don't do blocking work on the UI thread 不要在UI线程上进行阻塞工作

You can consider using BackgroundWorker or Task.Run or async/await pattern instead. 您可以考虑改用BackgroundWorker或Task.Run或async / await模式。

As an example: 举个例子:

private async void button1_Click(object sender, EventArgs e)
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 10000; i++)
        {
            this.Invoke(new Action(() =>
            {
                label1.Text = i.ToString();
                label1.Refresh();
            }));
        }
    });
}

This way the numbers increase, the label refreshes and shows the new value, while the UI is responsive and for example you can move your form or click on other button. 这样,数字会增加,标签会刷新并显示新值,而UI会响应,例如,您可以移动表单或单击其他按钮。

You should put your UI related codes in an action fired by Invoke to prevent receiving cross thread operation exception. 您应该将与UI相关的代码放入Invoke触发的操作中,以防止收到跨线程操作异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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