c# 如何 change/access 来自不同 class 的 WinForms 控件
c# How to change/access WinForms controls from a different class
因此,我正在尝试从另一个 class 而非表单 class 更改 WinForms 项目中的文本。
它应该像这样工作:
但它是这样做的:
我过去的做法是将对象作为参数传递给我的另一个 class,然后从另一个 class 我可以更改文本。我对进度条做了同样的事情,它确实在那里工作,所以它适用于进度条而不是标签很奇怪。
我用这个方法改变进度条:
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);
}
这里是我使用方法的地方:
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!");
}
现在我知道这段代码是有效的,因为进度条在增加。它应该跳入第一个 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);
您可以在设置 Text
后调用 lblStatus.Refresh();
强制重绘控件。
但请考虑 Slaks 评论:
Don't do blocking work on the UI thread
您可以考虑改用 BackgroundWorker 或 Task.Run 或 async/await 模式。
举个例子:
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();
}));
}
});
}
这样数字会增加,标签会刷新并显示新值,而 UI 是响应式的,例如您可以移动表单或单击其他按钮。
您应该将您的 UI 相关代码放在由 Invoke
触发的操作中,以防止收到跨线程操作异常。
因此,我正在尝试从另一个 class 而非表单 class 更改 WinForms 项目中的文本。 它应该像这样工作:
但它是这样做的:
我过去的做法是将对象作为参数传递给我的另一个 class,然后从另一个 class 我可以更改文本。我对进度条做了同样的事情,它确实在那里工作,所以它适用于进度条而不是标签很奇怪。
我用这个方法改变进度条:
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);
}
这里是我使用方法的地方:
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!");
}
现在我知道这段代码是有效的,因为进度条在增加。它应该跳入第一个 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);
您可以在设置 Text
后调用 lblStatus.Refresh();
强制重绘控件。
但请考虑 Slaks 评论:
Don't do blocking work on the UI thread
您可以考虑改用 BackgroundWorker 或 Task.Run 或 async/await 模式。
举个例子:
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();
}));
}
});
}
这样数字会增加,标签会刷新并显示新值,而 UI 是响应式的,例如您可以移动表单或单击其他按钮。
您应该将您的 UI 相关代码放在由 Invoke
触发的操作中,以防止收到跨线程操作异常。