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

控制ElementTypeDuplicated事件后,如何覆盖IDD_SYMBOL_ATTRIB对话框结果?

解决Revit中覆盖ElementTypeDuplicated事件对应对话框结果的问题

我明白你遇到的痛点了——ElementTypeDuplicated事件确实是在用户输入新名称并确认对话框后才触发的,这时候事件参数里的信息已经是最终结果,直接修改参数自然不会生效。要实现你想要的效果,得换个思路:在对话框弹出时就介入控制,而不是等事件触发后再补救。

下面给你两种可行的方案,你可以根据需求选择:

方案1:拦截对话框并修改输入内容

利用Revit API的DialogBoxShowing事件,监听ID为IDD_SYMBOL_ATTRIB的对话框,在它显示时直接修改输入框里的名称,这样用户确认后就会用你指定的名称完成复制。

示例代码

首先订阅DialogBoxShowing事件:

private ControlledApplication _controlledApp;

public void Initialize()
{
    _controlledApp = new ControlledApplication();
    _controlledApp.DialogBoxShowing += OnDialogBoxShowing;
}

然后编写事件处理方法(需要引用System.Windows.Automation程序集,用来操作对话框控件):

using System.Windows.Automation;

private void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs e)
{
    // 确认当前弹出的是目标对话框
    if (e.DialogId.Equals("IDD_SYMBOL_ATTRIB", StringComparison.OrdinalIgnoreCase))
    {
        // 通过对话框句柄获取自动化元素
        var dialogElement = AutomationElement.FromHandle(e.DialogHandle);
        if (dialogElement == null) return;

        // 找到名称输入框(注意:不同Revit版本的控件Automation ID可能有差异,需用Inspect工具确认)
        var nameInput = dialogElement.FindFirst(
            TreeScope.Descendants,
            new PropertyCondition(AutomationElement.AutomationIdProperty, "txtName")); // 示例ID,实际需验证

        if (nameInput != null && nameInput.Current.IsEnabled)
        {
            // 设置输入框的值为你想要的名称
            var valuePattern = nameInput.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
            valuePattern?.SetValue("你的自定义类型名称");
        }
    }
}

方案2:取消默认对话框,手动复制ElementType

如果不想依赖UI自动化,也可以直接取消默认的对话框,自己调用API完成复制流程,完全控制新类型的名称。

示例代码

先订阅SelectionChanged事件获取用户选中的ElementType,再在DialogBoxShowing里处理:

private ElementType _pendingDuplicateType; // 提前保存用户选中的ElementType

public void Initialize()
{
    _controlledApp.SelectionChanged += OnSelectionChanged;
    _controlledApp.DialogBoxShowing += OnDialogBoxShowing;
}

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // 保存用户选中的第一个ElementType
    _pendingDuplicateType = e.GetSelectedElements()
        .FirstOrDefault(el => el is ElementType) as ElementType;
}

private void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs e)
{
    if (e.DialogId.Equals("IDD_SYMBOL_ATTRIB", StringComparison.OrdinalIgnoreCase) && _pendingDuplicateType != null)
    {
        // 取消默认对话框
        e.Cancel = true;

        // 手动启动事务复制类型
        using (var trans = new Transaction(_pendingDuplicateType.Document, "自定义复制类型"))
        {
            trans.Start();
            // 直接指定新名称
            var newTypeId = _pendingDuplicateType.Duplicate("你的自定义类型名称");
            trans.Commit();

            // 可选:选中新生成的类型
            _pendingDuplicateType.Document.SelectElement(newTypeId);
        }

        // 清空临时变量
        _pendingDuplicateType = null;
    }
}

备选方案:事后修改类型名称(不推荐)

如果以上两种方案都不适用,你也可以在ElementTypeDuplicated事件触发后,修改新生成类型的名称,但这样用户会先看到自己输入的名称,然后被替换,体验不够流畅:

private void OnElementTypeDuplicated(object sender, ElementTypeDuplicatedEventArgs e)
{
    var doc = (sender as ControlledApplication).ActiveUIDocument?.Document;
    if (doc == null) return;

    var newTypeId = e.GetNewTypeId();
    using (var trans = new Transaction(doc, "重命名复制类型"))
    {
        trans.Start();
        var newType = doc.GetElement(newTypeId) as ElementType;
        if (newType != null)
        {
            newType.Name = "你的自定义类型名称";
        }
        trans.Commit();
    }
}

关键说明

  • ElementTypeDuplicated是事后通知事件:它在类型已经复制完成后触发,所以此时修改事件参数无法改变已经完成的操作。
  • 优先选择方案1或2:这两种方案都是在对话框显示阶段介入,能完全控制最终的类型名称,用户体验更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:08:54