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

DocumentChanged事件只读时,如何设置元素参数(排除IUpdater)

可行实现思路(排除IUpdater)

首先明确:你在DocumentChanged事件里直接启动事务修改元素会失败,因为这个事件触发时,文档正处于只读事务上下文(属于原变更事务的一部分),不允许启动新的修改事务。以下是两种无需IUpdater的可行方案:


方法一:利用Idling事件延迟执行修改

Idling是Revit空闲时触发的事件,此时文档处于可修改状态。我们可以在DocumentChanged中先收集需要修改的元素ID,等Idling触发时再批量处理。

代码示例

// 类级变量,暂存需要修改的元素ID(线程安全)
private readonly HashSet<ElementId> _pendingElementIds = new HashSet<ElementId>();

public Result OnStartup(UIControlledApplication application)
{
    try
    {
        application.ControlledApplication.DocumentChanged += Application_DocumentChanged;
        // 注册Idling事件
        application.Idling += Application_Idling;
    }
    catch (Exception)
    {
        return Result.Failed;
    }
    return Result.Succeeded;
}

private void Application_DocumentChanged(object sender, DocumentChangedEventArgs e)
{
    var addedIds = e.GetAddedElementIds();
    if (addedIds.Any())
    {
        lock (_pendingElementIds)
        {
            foreach (var id in addedIds)
            {
                _pendingElementIds.Add(id);
            }
        }
    }
}

private void Application_Idling(object sender, IdlingEventArgs e)
{
    lock (_pendingElementIds)
    {
        if (_pendingElementIds.Count == 0) return;

        var uiApp = sender as UIApplication;
        var doc = uiApp.ActiveUIDocument?.Document;
        if (doc == null) return;

        using (var trans = new Transaction(doc, "Set TCP Parameters"))
        {
            try
            {
                trans.Start();
                var paramGuid = new Guid("6558f207-e777-0758-2023-2f34e722cb01");
                foreach (var elId in _pendingElementIds)
                {
                    var elem = doc.GetElement(elId);
                    var param = elem.get_Parameter(paramGuid);
                    // 必须检查参数是否可修改,避免报错
                    if (param != null && !param.IsReadOnly)
                    {
                        param.Set(200);
                    }
                }
                trans.Commit();
            }
            catch (Exception ex)
            {
                TaskDialog.Show("Error", ex.Message);
                trans.RollBack();
            }
            finally
            {
                _pendingElementIds.Clear();
            }
        }
    }
}

方法二:监听TransactionCompleted事件

TransactionCompleted事件在文档的事务提交完成后触发,此时文档已经脱离只读状态,可以安全启动新事务修改元素。

代码示例

public Result OnStartup(UIControlledApplication application)
{
    try
    {
        // 监听文档打开事件,为每个文档绑定事务完成事件
        application.ControlledApplication.DocumentOpened += Application_DocumentOpened;
    }
    catch (Exception)
    {
        return Result.Failed;
    }
    return Result.Succeeded;
}

private void Application_DocumentOpened(object sender, DocumentOpenedEventArgs e)
{
    var doc = e.Document;
    // 为当前文档注册TransactionCompleted事件
    doc.TransactionCompleted += Doc_TransactionCompleted;
}

private void Doc_TransactionCompleted(object sender, TransactionCompletedEventArgs e)
{
    var doc = sender as Document;
    if (doc == null) return;

    // 获取当前事务新增的元素ID
    var addedIds = e.GetAddedElementIds();
    if (!addedIds.Any()) return;

    using (var trans = new Transaction(doc, "Set TCP Parameters"))
    {
        try
        {
            trans.Start();
            var paramGuid = new Guid("6558f207-e777-0758-2023-2f34e722cb01");
            foreach (var elId in addedIds)
            {
                var elem = doc.GetElement(elId);
                var param = elem.get_Parameter(paramGuid);
                if (param != null && !param.IsReadOnly)
                {
                    param.Set(200);
                }
            }
            trans.Commit();
        }
        catch (Exception ex)
        {
            TaskDialog.Show("Error", ex.Message);
            trans.RollBack();
        }
    }
}

注意事项

  1. 无论哪种方法,都要检查参数的IsReadOnly属性,避免修改系统或不可编辑参数导致报错。
  2. 多文档场景下,Idling方法的集合需要加锁保证线程安全;TransactionCompleted绑定到单个文档,无需额外处理并发。
  3. 两种方案都能覆盖所有文档变更场景,完全不需要依赖IUpdater。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:45:20