You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mono环境下C# BindingSource绑定Label控件失效问题求助

问题分析与解决方案

你的WinForms数据绑定代码在Windows环境下通过BeginInvoke调用UpdateControlValue正常工作,但在树莓派Raspbian的Mono环境中失效,核心原因是Mono对WinForms数据绑定的事件通知机制、线程模型的处理和.NET Framework存在差异,以下是针对性修复方案:

修复方案1:缓存BindingSource并显式触发绑定更新

原代码中AssignConstantToControl方法内的BindingSource是局部变量,更新DataTable后无法主动通知绑定控件刷新。需要缓存每个ControlMapEnum对应的BindingSource,更新后手动触发绑定刷新:

修改步骤:

  1. 添加缓存字典:
private Dictionary<ControlMapEnum, BindingSource> _bindingSources = new Dictionary<ControlMapEnum, BindingSource>();
  1. 修改AssignConstantToControl方法,将BindingSource存入字典:
public void AssignConstantToControl(List<System.Windows.Forms.Control> controlToAssociate, ControlMapEnum controlId)
{           
    BindingSource bs1 = new BindingSource();
    bs1.DataSource = ds;
    bs1.DataMember = TABLE_NAME;
    bs1.Filter = $"{COLUMN_NAME} = '{controlId.ToString()}'";

    // 缓存当前ControlId对应的BindingSource
    _bindingSources[controlId] = bs1;

    foreach (System.Windows.Forms.Control control in controlToAssociate)
        control.DataBindings.Add("Text", bs1, COLUMN_VALUE);
}
  1. 修改UpdateControlValue方法,更新后触发BindingSource刷新:
public void UpdateControlValue(ControlMapEnum controlId, string newValue)
{            
    DataRow dr = tabella1.Select($"{COLUMN_NAME} = '{controlId.ToString()}'").FirstOrDefault();
    if (dr == null)
        return;

    dr.BeginEdit();
    dr[COLUMN_VALUE] = newValue;
    dr.EndEdit();
    // 提交DataTable更改,确保状态同步
    tabella1.AcceptChanges();

    // 触发绑定控件刷新
    if (_bindingSources.TryGetValue(controlId, out var bs))
    {
        bs.ResetBindings(false);
    }

    LoggerManagerUtility.Instance.Log(LogLevel.Info, this, $"END UPDATE CONTROL {controlId} TEXT TO VISUALIZE: {newValue}");
}

修复方案2:强化UI线程同步(适配Mono线程模型)

Mono下WinForms的线程检查更严格,即使调用方使用了BeginInvoke,也建议在UpdateControlValue内部再次确认线程上下文:

public void UpdateControlValue(ControlMapEnum controlId, string newValue)
{
    // 以主窗体作为同步上下文,也可传入任意UI控件
    var mainForm = System.Windows.Forms.Application.OpenForms[0];
    if (mainForm.InvokeRequired)
    {
        mainForm.BeginInvoke(new Action(() => UpdateControlValue(controlId, newValue)));
        return;
    }

    DataRow dr = tabella1.Select($"{COLUMN_NAME} = '{controlId.ToString()}'").FirstOrDefault();
    if (dr == null)
        return;

    dr[COLUMN_VALUE] = newValue;
    tabella1.AcceptChanges();

    if (_bindingSources.TryGetValue(controlId, out var bs))
    {
        bs.ResetBindings(false);
    }

    LoggerManagerUtility.Instance.Log(LogLevel.Info, this, $"END UPDATE CONTROL {controlId} TEXT TO VISUALIZE: {newValue}");
}

修复方案3:优化DataRow查找逻辑(避免Mono语法兼容问题)

给DataTable设置主键,用Rows.Find代替Select方法,既提升性能又规避Mono对筛选语法的兼容差异:

public HmiMappingManager()
{            
    tabella1.Columns.Add(COLUMN_NAME, typeof(string));
    tabella1.Columns.Add(COLUMN_VALUE, typeof(string));
    // 设置主键,用于快速查找
    tabella1.PrimaryKey = new DataColumn[] { tabella1.Columns[COLUMN_NAME] };
    
    var values = Enum.GetValues(typeof(ControlMapEnum));
    foreach (var val in values)
    {
        ControlMapEnum enumVal = (ControlMapEnum)val;
        string defaultValue = DecorationHelper.GetDescription(enumVal);
        tabella1.Rows.Add(new object[2] { enumVal.ToString(), defaultValue });
    }

    ds.Tables.Add(tabella1);
    ds.AcceptChanges();
}

// 修改UpdateControlValue中的查找逻辑
public void UpdateControlValue(ControlMapEnum controlId, string newValue)
{            
    DataRow dr = tabella1.Rows.Find(controlId.ToString());
    if (dr == null)
        return;

    dr[COLUMN_VALUE] = newValue;
    tabella1.AcceptChanges();

    if (_bindingSources.TryGetValue(controlId, out var bs))
    {
        bs.ResetBindings(false);
    }

    LoggerManagerUtility.Instance.Log(LogLevel.Info, this, $"END UPDATE CONTROL {controlId} TEXT TO VISUALIZE: {newValue}");
}

额外注意事项

  • 确保使用最新稳定版Mono,旧版本WinForms绑定存在已知bug;
  • 禁止在非UI线程直接修改DataTable,即使Mono允许,也可能导致绑定失效;
  • 测试时可添加调试日志,确认UpdateControlValue是否被执行、DataRow值是否正确修改。

内容的提问来源于stack exchange,提问作者user15536099

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:54:22