You need to enable JavaScript to run this app. DevExpress WinForm GridLookUpEdit ProcessNewValue异步保存无法选中新增值
优惠活动
大模型
产品
解决方案
定价
更多

DevExpress WinForm GridLookUpEdit ProcessNewValue异步保存无法选中新增值

问题原因
  • GridLookUpEdit 的 ProcessNewValue 是同步触发的UI线程事件,WinForm的事件处理方法只能用 async void 修饰,控件内部不会等待方法里的 await 操作完成。当代码执行到 await _context.Provincias.GuardarAsync(provincia) 时,UI线程会立刻中断当前异步方法的执行,返回给控件的事件触发逻辑,根据此时的状态(还没标记新值已处理、还没加新数据源、还没更新选中值)走默认流程。
  • e.Handled 的设置时机过晚:你把 e.Handled = true 放在finally块中,要等异步操作全部完成才会执行,但 e.Handled 默认值是 false——这个参数的作用是告知控件是否要自行处理输入的新值,默认false时控件会自己做匹配:找不到对应已有值就直接还原之前的选中状态、清空输入框。等你异步跑完才把e.Handled设为true,控件早就完成状态重置了,后续修改显示值、添加数据源都不会再触发选中逻辑。
  • 仅修改e.DisplayValue无法触发选中:GridLookUpEdit的选中状态是和EditValue(绑定ValueMember指定的主键字段)联动的,仅修改显示文本不会触发绑定层的选中更新。
对应解决方法

核心逻辑:先告知控件接管新值处理、阻止其走默认清空逻辑,再执行异步保存,最后显式指定要选中的新记录主键。

方法一:调整代码执行顺序(推荐)

在执行异步操作前就设置e.Handled = true,异步完成后显式绑定新记录的EditValue,修改后的代码如下:

private async void GridLookUpEdit_ProcessNewValue(object sender, DevExpress.XtraEditors.Controls.ProcessNewValueEventArgs e)
{
    DevExpress.XtraEditors.GridLookUpEdit gridLookUp = sender as DevExpress.XtraEditors.GridLookUpEdit;
    try
    {
        var pais = cboPais.EditValue?.ToString();
        if (string.IsNullOrWhiteSpace(pais))
        {
            e.Handled = true;
            return;
        }

        if ((string)e.DisplayValue != String.Empty && FrameUtil.MostrarMensage(
                    this, "Confirmar", "Desea crear un registro nuevo ?", "La provincia o estado  '" + e.DisplayValue.ToString() + "' aun no se a agregado al pais " +
                    pais + Environment.NewLine + "Presione si para continuar y agregarlo",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
        {
            // 提前标记新值已接管,阻止控件走默认清空/还原逻辑
            e.Handled = true;

            ProvinciaDto provincia = new ProvinciaDto()
            {
                CodigoPais = pais,
                Descripcion = e.DisplayValue.ToString()
            };

            await _context.Provincias.GuardarAsync(provincia);

            ListaGenerica<ProvinciaDto> listaProvincias = bsProvincia.DataSource as ListaGenerica<ProvinciaDto>;
            listaProvincias.Add(provincia);

            // 先刷新数据源绑定,再显式设置EditValue为新记录的主键(替换为你实际的主键属性名)
            gridLookUp.RefreshDataSource();
            gridLookUp.EditValue = provincia.ProvinciaId; 
        }
    }
    catch (Exception ex)
    {
        FrameUtil.MostrarMensageError(this, ex);
    }
}

注意事项:

  • 原finally块中的e.Handled = true可以直接移除,避免重复设置。
  • 必须显式设置EditValue为新实体的主键(对应gridLookUp.Properties.ValueMember的配置字段),仅修改DisplayValue无法触发选中。
  • RefreshDataSource()是DevExpress控件专门用来重载绑定数据源的方法,比普通Refresh()更适配绑定更新场景。

方法二:异步完成后强制重载状态

如果不想调整原有代码的执行顺序,可以在异步操作全部完成后,手动重载控件的数据源并指定选中值:

  1. 给列表添加新项后,调用 gridLookUp.Properties.DataSource = listaProvincias; 强制重载数据源
  2. 再执行 gridLookUp.EditValue = provincia.ProvinciaId; 手动指定选中的新记录
常见踩坑提醒
  • 确认你的ListaGenerica列表实现了INotifyCollectionChanged接口(比如继承自BindingList<T>),否则添加新项后控件无法自动感知到数据源变化。
  • WinForm下await默认会自动切回UI线程,不需要额外加线程切换逻辑;如果自定义了异步调度规则,需要手动切回UI线程再操作控件,否则会触发跨线程操作异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 06:54:03