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

WPF开发Revit插件调用SendKeys.Send("{ESC}")引发UI不更新问题

问题根因
  • System.Windows.Forms.SendKeys.Send为同步阻塞执行,发送ESC按键到Revit后,Revit抛出的异常会打断当前WPF线程的消息路由,导致Checked/Unchecked事件的绑定更新、UI渲染逻辑未完成就被中止。
  • 发送ESC前主动激活了Revit窗口,WPF窗口的消息循环优先级被压低,属性变更通知无法及时被渲染线程处理。
  • 绑定未显式指定双向模式与实时更新触发器,存在属性同步失败的隐患。
修复方案

1. 修改绑定配置

显式指定CheckBox的绑定为双向模式,属性变更时立即触发同步:

<CheckBox IsChecked="{Binding Path=IsMultiselection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Checked="multiselection_chk_Checked" Unchecked="multiselection_chk_UnChecked"/>

同时确认窗口的DataContext已正确赋值为你实例化的ViewModel对象。

2. 异步执行Revit按键操作

将发送ESC的逻辑放到WPF消息队列的低优先级任务中,等UI更新完成后再执行,避免阻塞UI逻辑。同时替换SendKeys为更稳定的Win32 PostMessage API发送按键消息,不会阻塞当前线程:

// 导入Win32 API
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private const int WM_KEYDOWN = 0x0100;
private const int VK_ESCAPE = 0x1B;

private void multiselection_chk_Checked(object sender, RoutedEventArgs e)
{
    MultiselectChanged = true;
    // 低优先级异步执行,等待WPF完成UI渲染后再操作Revit
    Dispatcher.BeginInvoke(new Action(() =>
    {
        ActivateRevitWindow();
        // 发送ESC到Revit主窗口
        PostMessage(Autodesk.Revit.ApplicationServices.Application.MainWindowHandle, WM_KEYDOWN, (IntPtr)VK_ESCAPE, IntPtr.Zero);
    }), System.Windows.Threading.DispatcherPriority.Background);
}

private void multiselection_chk_UnChecked(object sender, RoutedEventArgs e)
{
    MultiselectChanged = true;
    Dispatcher.BeginInvoke(new Action(() =>
    {
        ActivateRevitWindow();
        PostMessage(Autodesk.Revit.ApplicationServices.Application.MainWindowHandle, WM_KEYDOWN, (IntPtr)VK_ESCAPE, IntPtr.Zero);
    }), System.Windows.Threading.DispatcherPriority.Background);
}
优化建议
  • 尽量避免模拟按键操作Revit,可通过UIDocument.Selection.SetElementIds(Array.Empty<ElementId>())直接清空选择,或者调用UIApplication.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.Cancel))触发原生取消命令,稳定性更高。
  • 所有对Revit API的调用都建议通过ExternalEvent触发,符合Revit的线程安全规范,避免跨线程异常。

内容的提问来源于stack exchange,提问作者adam.k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:24:04