WinForms中子类/孙类向UI传递数据的最优实现方法
WinForms中子类/孙类向UI传递数据的可行方案
针对需要将Loader类中的string result传递到Form UI的场景,以下是几种实用且解耦的实现方案:
方案1:使用IProgress接口(推荐)
WinForms的IProgress<T>接口会自动将回调逻辑切换到UI线程,无需手动处理线程切换,非常适合UI更新场景。
代码修改:
Loader类
public class Loader { private readonly IProgress<string> _logProgress; // 构造时注入IProgress实例 public Loader(IProgress<string> logProgress) { _logProgress = logProgress; } public DataTable GetGardensDataTable() { DataTable dataTable = new DataTable(); Dictionary<string, object> gardensDetails = new Dictionary<string, object>(); foreach(DataRow row in dataTable.Rows) { if (gardensDetails.ContainsKey(row[2].ToString())) { _log.AddToLog($"Found production duplicate: + {row[2].ToString()}", Color.Red); string result = _log.GetLogAsRichText(true); // 传递日志结果到UI _logProgress?.Report(result); continue; } // 其他业务逻辑... } return dataTable; } }
DataGridDataSource类
public class DataGridDataSource { private readonly Loader _loader; private readonly ProgressBar _progressBar; public DataGridDataSource(ProgressBar progressBar, IProgress<string> logProgress) { _progressBar = progressBar; _loader = new Loader(logProgress); } public DataTable GetDataSource() { DataTable gardensTable = _loader.GetGardensDataTable(); return gardensTable; } }
Form类
private async void Bt_Load_Click(object sender, EventArgs e) { // 创建Progress实例,直接在回调中更新UI(自动切换到UI线程) var logProgress = new Progress<string>(result => { // 假设用RichTextBox显示日志结果 richTextBoxLog.Rtf = result; }); DataGridDataSource dataGridDataSource = new DataGridDataSource(_progressBar, logProgress); // 用Task.Run避免阻塞UI线程 dataSource = await Task.Run(() => dataGridDataSource.GetDataSource()); }
方案2:事件委托机制
通过定义事件,让Loader触发事件传递数据,Form订阅事件接收数据,适合需要多个订阅者的场景。
代码修改:
Loader类
public class Loader { // 定义传递日志结果的事件 public event Action<string> LogResultGenerated; public DataTable GetGardensDataTable() { DataTable dataTable = new DataTable(); Dictionary<string, object> gardensDetails = new Dictionary<string, object>(); foreach(DataRow row in dataTable.Rows) { if (gardensDetails.ContainsKey(row[2].ToString())) { _log.AddToLog($"Found production duplicate: + {row[2].ToString()}", Color.Red); string result = _log.GetLogAsRichText(true); // 触发事件传递结果 LogResultGenerated?.Invoke(result); continue; } // 其他业务逻辑... } return dataTable; } }
DataGridDataSource类
public class DataGridDataSource { private readonly Loader _loader; private readonly ProgressBar _progressBar; public DataGridDataSource(ProgressBar progressBar) { _progressBar = progressBar; _loader = new Loader(); // 转发Loader的事件到外部 _loader.LogResultGenerated += (result) => LogResultGenerated?.Invoke(result); } // 暴露给Form的事件 public event Action<string> LogResultGenerated; public DataTable GetDataSource() { DataTable gardensTable = _loader.GetGardensDataTable(); return gardensTable; } }
Form类
private async void Bt_Load_Click(object sender, EventArgs e) { DataGridDataSource dataGridDataSource = new DataGridDataSource(_progressBar); // 订阅事件 dataGridDataSource.LogResultGenerated += UpdateLogUI; dataSource = await Task.Run(() => dataGridDataSource.GetDataSource()); } private void UpdateLogUI(string result) { // 手动判断是否需要切换到UI线程 if (richTextBoxLog.InvokeRequired) { richTextBoxLog.Invoke(new Action<string>(UpdateLogUI), result); return; } richTextBoxLog.Rtf = result; }
方案3:回调函数传递
直接将UI更新方法作为回调传递给Loader,适合简单的一对一数据传递场景。
代码修改:
Loader类
public class Loader { private readonly Action<string> _logCallback; // 构造时注入回调方法 public Loader(Action<string> logCallback) { _logCallback = logCallback; } public DataTable GetGardensDataTable() { DataTable dataTable = new DataTable(); Dictionary<string, object> gardensDetails = new Dictionary<string, object>(); foreach(DataRow row in dataTable.Rows) { if (gardensDetails.ContainsKey(row[2].ToString())) { _log.AddToLog($"Found production duplicate: + {row[2].ToString()}", Color.Red); string result = _log.GetLogAsRichText(true); // 调用回调传递结果 _logCallback?.Invoke(result); continue; } // 其他业务逻辑... } return dataTable; } }
DataGridDataSource类
public class DataGridDataSource { private readonly Loader _loader; private readonly ProgressBar _progressBar; public DataGridDataSource(ProgressBar progressBar, Action<string> logCallback) { _progressBar = progressBar; _loader = new Loader(logCallback); } public DataTable GetDataSource() { DataTable gardensTable = _loader.GetGardensDataTable(); return gardensTable; } }
Form类
private async void Bt_Load_Click(object sender, EventArgs e) { DataGridDataSource dataGridDataSource = new DataGridDataSource(_progressBar, UpdateLogUI); dataSource = await Task.Run(() => dataGridDataSource.GetDataSource()); } private void UpdateLogUI(string result) { if (richTextBoxLog.InvokeRequired) { richTextBoxLog.Invoke(new Action<string>(UpdateLogUI), result); return; } richTextBoxLog.Rtf = result; }
内容的提问来源于stack exchange,提问作者Guinea Pig Taco
相关产品推荐
相关产品推荐

