我正在开发一个 MDI 应用程序,用户可以在其中创建同一表单的多个实例(称为 ListForm)。ListForm 的每个实例都有一个 flowlayoutpanel,其中包含一组唯一的用户控件。ListForm 还包含一个 StatusStrip ProgressBar 和一个名为“ReadAll”的按钮。
每个用户控件都有一个“读取”按钮,单击该按钮将执行读取操作。此操作最多可能需要 3 秒才能完成。
我想要做的是当用户单击“ReadAll”按钮时,子窗体会生成一个后台线程,该线程遍历 flowlayoutpanel.controls 集合并调用每个用户控件的 .PerformClick() 方法。这将更新表单中的所有用户控件。
问题在于,看起来所有表单实例的事件处理程序都被调用,导致 ListForm 的所有实例中的所有用户控件都被更新。此外,当我从后台工作人员报告进度时,所有 ListForm 实例的进度条都会更新。不需要此功能。
如何确保仅更新生成后台工作人员的 ListForm?是否有唯一标识子表单的首选方法?
在此先感谢您的帮助。代码如下...
public partial class ListForm: Form
{
// Background Worker Thread for Read / Write All tasks
private static BackgroundWorker bw = new BackgroundWorker();
public ListForm()
{
InitializeComponent();
// Configure the Background Worker that reads and writes all variable data
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
private void btnReadAll_Click(object sender, EventArgs e)
{
if (bw.IsBusy != true)
{
// Start the ReadAll parameters thread
btnReadAll.Text = "Cancel Read";
btnWriteAll.Enabled = false;
bw.RunWorkerAsync("R");
}
else if (bw.WorkerSupportsCancellation == true)
{
// Cancel the ReadAll parameters thread
bw.CancelAsync();
}
}
// ****************************** Background Thread Methods ***************************
public delegate void DoUIWorkHandler();
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
DoUIWorkHandler DoReadClick;
DoUIWorkHandler DoWriteClick;
int CurrentControlCount = 1;
string StatusText = "";
int ProgressValue = 0;
string argument = e.Argument as string;
// *******************Perform a time consuming operation and report progress.
try
{
foreach (UserControl c in this.flowLayoutPanel1.Controls)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Update the status and return it to the UI
StatusText = "Updating: (" + (CurrentControlCount).ToString() + " of " + flowLayoutPanel1.Controls.Count.ToString() + ") " + c.ParamProperties.strDHIndexDescription;
ProgressValue = (int)(((float)CurrentControlCount / (float)flowLayoutPanel1.Controls.Count) * 100);
worker.ReportProgress(ProgressValue, StatusText);
System.Threading.Thread.Sleep(20);
CurrentControlCount++;
// Update the contorl
if (c.InvokeRequired)
{
if (argument == "R")
{
DoReadClick = c.btnRead.PerformClick;
c.Invoke(DoReadClick);
}
else
{
DoWriteClick = c.btnWrite.PerformClick;
c.Invoke(DoWriteClick);
}
}
}
}
}
catch(InvalidCastException ex)
{
// Catch any functions that are in the Layout panel
string ErrorStr = "Could not cast a Function control to a Parameter control. \n\r\r Exception: " + ex.Message;
srvcAppLogger.Logger.Log(new clsApplicationLogger.LoggerMessage(ErrorStr, "bw_DoWork", "frmVariableHandlerGUI"));
}
catch (Exception ex)
{
string ErrorStr = "An unecpected exception occured. Error: " + ex.Message.ToString();
srvcAppLogger.Logger.Log(new clsApplicationLogger.LoggerMessage(ErrorStr, "bw_DoWork", "frmVariableHandlerGUI"));
}
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.tsStatus.Text = e.UserState.ToString();
this.tsProgressBar.Value = e.ProgressPercentage;
}