8. Revit API UI: DockablePane(可停靠窗口)

8. Revit API UI: DockablePane(可停靠窗口)

接着前面的预览控件和外部事件,这一篇,我们来看看可停靠窗口DockablePane的实现。

实现流程

可停靠窗口相关的类与接口主要有DockablePaneIDockablePageProvider,都是在UI命名空间下。

流程:

  1. 创建一个Page页,并实现IDockablePageProvider接口;
  2. 生成一个DockablePaneId,需要传入一个Guid,所以最好建立一个映射表;
  3. 在插件入口(即IExteranlApplication)中注册该窗口,使用UIControlledApplication.RegisterDockablePane(..)方法;
  4. 使用时,通过uiApp.GetDockablePane(dpId)方法检索到可停靠窗体,调用Show()显示窗体。

先实现,后面再讲讲我个人测试的遇到的问题。

示例

本例想接着用上一篇用到的预览窗体界面,但Revit启动时显然是没有View的,就算了。

  1. XAML:新建一个叫"DockablePage"的Page,里头随便放些东西。记得要实现IDockablePageProvider接口。

  2. IExternalApplication:在外部应用启动时注册。

c 复制代码
[Transaction(TransactionMode.Manual)]
[Journaling(JournalingMode.NoCommandData)]
public class Application : IExternalApplication
{
    public Result OnStartup(UIControlledApplication application)
    {
        this.RegisterDockablePane(application);
        return Result.Succeeded;
    }

    public Result OnShutdown(UIControlledApplication application)
    {
        return Result.Succeeded;
    }
    
    private void RegisterDockablePane(UIControlledApplication application)
    {
        DockablePaneId dockablePaneId = new DockablePaneId(new Guid(Mapping.DockablePaneId));  // 生成ID
        application.RegisterDockablePane(dockablePaneId, "DockablePane", DockablePage.GetDockablePage());  // 进行注册
    }
}
  1. IExternalCommand:在外部命令中使用。
c 复制代码
[Transaction(TransactionMode.Manual)]
[Journaling(JournalingMode.NoCommandData)]
internal class DockablePaneCommand : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        UIApplication uiApp = commandData.Application;
        
        DockablePaneId dockablePaneId = new DockablePaneId(new Guid(Mapping.DockablePaneId));  // 创建ID,根据ID查找
        //TaskDialog.Show("DockablePaneCommand", $"{DockablePane.PaneIsRegistered(dockablePaneId)}\r\n" + $"{DockablePane.PaneExists(dockablePaneId)}");
        DockablePane dockablePane = uiApp.GetDockablePane(dockablePaneId);

        dockablePane.Show();
        return Result.Succeeded;
    }
}

至此,一个完整的可停靠窗口的Demo就完成了。

记录问题

1. 必须在外部应用中注册吗

如果你了解Application相关API,就能够知道UIControlledApplicationUIApplication的大部分类成员都是一样的,效果一样。不了解没关系可以看这篇:5. Revit API: Application

那么,就一定得在外部应用中注册?

是的,必须在外部应用中注册。

能不能在外部命令中,通过UIApplication注册呢?

答案是可以的,但是只能注册,无法显示。

DockablePane 类中有3个静态方法,通过传入DockablePaneId 进行检测。

方法 描述
PaneIsBuiltIn(dpID) 检测目标窗口是否为Revit内置窗口
PaneIsRegistered(dpID) 检测目标窗口是否已注册
PaneExists(dpID) 检测目标窗口是否已创建

通过这三个方法,可以得到结果:

注册位置 内置 已注册 已创建
IExternalApplication
IExternalCommand

当在外部命令中注册,并调用Show()方法时,会报错。

2. 必须用Page吗

虽然API文档中写建议使用Page及其派生类。那我可偏要看看不用能咋样。

好吧,不用界面就黑了。

Window不行,PageUserControl都可以。Window是最高级别的UI元素,猜测非Window都可以。

下面是使用Window和UserControl的截图

3. 可停靠窗口中,可以放外部事件吗

可以

上面说了,最开始是想直接使用上一篇的界面,那上面就有ExternalEvent,我测试了那个删除按钮还是有效的。

4. 如何让可停靠窗口的内容变化

例子中创建了个表格,就是想从项目文档中获取信息,进行展示。就像Revit自带的那些窗口一样,内容可以变化,想想就很棒是不是,可惜不得行。

不知道,不会,没搞定😶

好吧,没搞定。

DockablePane类中,并没有获取窗体的方法或属性,于是尝试曲线修改。

  • 尝试让数据表绑定在一个静态变量上,可是数据变了没效果。

  • 尝试将页面设为单例,改了还是无效。

然后就没有然后了,怀疑注册时传进去的和Revit创建的就不是同一个东西。

5. 遇到的其它问题

遇到了一个"无法初始化附加模块xxx,因为".../xx.dll"不存在"的问题。

显然这破问题的原因不在于那个dll不存在。

问题在哪儿呢?还是之前写Ribbon时偷懒了,直接用"xxx"代替了。

这里问题的原因是,Ribbon控件里,命令的路径错了

Ribbon那篇没有示例图片,这里补充一个吧。

c 复制代码
private void CreateRibbon(UIControlledApplication application)
{
    string tabName = "Samples";
    string panelName = "Commands";
    RibbonPanel panel = application.CreatePanel(panelName, tabName);

    PushButtonData buttonData_single = new PushButtonData("单个按钮", "单个按钮", addInPath, "RevitAPISamples.Commands.Dialog")
    {
        LargeImage = new BitmapImage(new Uri(Path.Combine(this.buttonIconsFolder, "CreateWall.png"))),
        Image = new BitmapImage(new Uri(Path.Combine(this.buttonIconsFolder, "CreateWall.png"))),
        ToolTip = "按钮(单个)",
        LongDescription = "鼠标放按钮上,就会出现这段文字",
        ToolTipImage = new BitmapImage(new Uri(Path.Combine(this.buttonIconsFolder, "Revit.png"))),
    };
    ContextualHelp contextualHelp = new ContextualHelp(ContextualHelpType.Url, "https://thebuildingcoder.typepad.com/blog/2020/09/on-spaces-in-help-and-renaming-a-parameter.html");
    buttonData_single.SetContextualHelp(contextualHelp);
    panel.AddItem(buttonData_single);
}

总结

UI篇还有多少来着,不记得了,得去翻翻之前的图。

这篇就到这里了,下篇写什么呢,emm...。

相关推荐
AIWhispers38 分钟前
【C++笔记整理—第1期】
开发语言·c++·笔记
杨树与晨光1 小时前
常用字符串方法<python>
开发语言·笔记·python
InterestingFigure1 小时前
软件测试学习笔记丨JUnit5标记测试用例
笔记·学习·测试用例
!!!!!!!!!!!!!!!!.2 小时前
记一次小程序渗透
笔记·安全·web安全·小程序
qq8368695204 小时前
Head First设计模式学习笔记
笔记·学习·设计模式
Jizhi_Zhang5 小时前
Python学习笔记17 -- 猜数字小游戏2
笔记·python·学习
手打猪大屁5 小时前
STM32——使用TIM输出比较产生PWM波形控制舵机转角
笔记·stm32·单片机·嵌入式硬件·学习·舵机
ender6706 小时前
【计算机网络】HTTPS——更安全的HTTP通信(个人笔记)
笔记·计算机网络
大学生小郑6 小时前
操作系统期末复习考题三(不挂科系列)
笔记·学习·学习方法
大学生小郑6 小时前
操作系统期末复习真题四
笔记·学习·学习方法