WPF底层使用 DirectX 进行图形渲染。DirectX  能理解可由显卡直接渲染的高层元素,如纹理和渐变,所以 DirectX 效率更高。而 GDI/GDI+不理解这些高层元素,因此必须将他们转换成逐像素指令,而通过现代显卡渲染这些指令更慢。WinForm 的绘图技术使用的就是GDI/GDI+技术。但是xBIM并没有提供专门针对传统 WinForm 技术的的模型查看器。如果确实需要在传统的 WinForm 窗体中也要加载并显示BIM(.ifc格式)模型文件该如何处理呢?

  由于WinForm与WPF技术可以互通互用,所以本文介绍一种取巧的方式,在WinForm窗体中加载WPF控件,WPF控件中渲染BIM(.ifc格式)模型文件。具体操作步骤如下详细介绍。

一、新建WinForm项目
   新建WinForm项目,.NET Framework 选择4.7版本,因为需要引用最新的 XBIM相关DLL(依赖 .NET Framework 4.7)。 
二、添加xBIM相关DLL引用
  通过NuGet程序包管理器添加xBIM相关的DLL引用
 需要应用下列DLL
三、添加WPF相关DLL引用
  通过NuGet程序包管理器添加WPF相关的DLL引用。其中 HelixToolkit 是开发wpf3D应用的开源库,比较好用。

添加引用后,自动添加了下列WPF的基础库。

四、在Winform项目中添加WPF用户控件

编写XAML代码如下:

 <UserControl x:Class="Xbim.WinformsSample.WinformsAccessibleControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:presentation="http://schemas.Xbim.com/Presentation"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800"
x:Name="MainWindow"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid Name="MainFrame">
<presentation:DrawingControl3D x:Name="DrawingControl"
x:FieldModifier="public"
Model ="{Binding ModelProvider.ObjectInstance}"
Focusable="True"
Width="Auto"
Height="Auto"
SelectedEntityChanged="DrawingControl_SelectedEntityChanged"
ModelOpacity="1">
</presentation:DrawingControl3D>
</Grid>
</UserControl>

其中第12行,引用了 xBIM官方提供的 模型浏览器组件。显示效果如下:

五、在WinForm窗体中调用WPF查看器

  添加一个WinForm窗体。左侧Panel中是 按钮区域,右侧Panel填充窗体剩余的所有区域。

 
打开VS的工具箱,可以看到如下栏目
 
WPF互操作性,将 “ElementHost”控件拖拽到右侧Panel中,命名为controlHost,并设置 Dock 属性为 Fill。

后台逻辑:在第四步骤中创建了一个WPF用户控件,在此处实例化一个对象

private WinformsAccessibleControl _wpfControl;

在构造函数中初始化该对象并将对象添加到 controlHost 中

  public FormExample(ILogger logger = null)
{
InitializeComponent(); Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>(); IfcStore.ModelProviderFactory.UseHeuristicModelProvider(); _wpfControl = new WinformsAccessibleControl();
_wpfControl.SelectionChanged += _wpfControl_SelectionChanged; controlHost.Child = _wpfControl;
}

运行效果如下:

完整的示例代码如下:

 using System;
using System.Linq;
using System.Windows.Forms; using Microsoft.Extensions.Logging; using Xbim.Common;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;
using Xbim.ModelGeometry.Scene; namespace Xbim.WinformsSample
{
public partial class FormExample : Form
{
private WinformsAccessibleControl _wpfControl; int starting = -; protected ILogger Logger { get; private set; } public FormExample(ILogger logger = null)
{
InitializeComponent(); Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>(); IfcStore.ModelProviderFactory.UseHeuristicModelProvider(); _wpfControl = new WinformsAccessibleControl();
_wpfControl.SelectionChanged += _wpfControl_SelectionChanged; controlHost.Child = _wpfControl;
} private void _wpfControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
var ent = e.AddedItems[] as IPersistEntity;
txtEntityLabel.Text = ent == null ? "" : ent.EntityLabel.ToString();
} /// <summary>
/// 打开BIM(.ifc格式)文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnLoadBimFile_Click(object sender, EventArgs e)
{
var dlg = new OpenFileDialog();
dlg.Filter = @"IFC Files|*.ifc;*.ifczip;*.ifcxml|Xbim Files|*.xbim";
dlg.FileOk += (s, args) =>
{
LoadXbimFile(dlg.FileName);
};
dlg.ShowDialog(this);
} /// <summary>
/// 查看模型实体标签
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnNext_Click(object sender, EventArgs e)
{
var mod = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
if (mod == null)
return; var found = mod.Instances.OfType<IIfcProduct>().FirstOrDefault(x => x.EntityLabel > starting);
_wpfControl.SelectedElement = found; if(found != null)
{
starting = found.EntityLabel;
}
else
{
starting = -;
}
} /// <summary>
/// 加载BIM(.ifc格式)文件
/// </summary>
/// <param name="dlgFileName"></param>
private void LoadXbimFile(string dlgFileName)
{
// TODO: should do the load on a worker thread so as not to lock the UI.
// 如果加载的模型文件较大,耗时可能较长,建议使用后要程序处理,给用户一个好的使用体验。 Clear(); var model = IfcStore.Open(dlgFileName);
if (model.GeometryStore.IsEmpty)
{
// 使用 xBIM 几何引擎创建 GeometryEngine 对象
try
{
var context = new Xbim3DModelContext(model); context.CreateContext(); // TODO: SaveAs(xbimFile); // so we don't re-process every time
}
catch (Exception geomEx)
{
Logger.LogError(, geomEx, "Failed to create geometry for {filename}", dlgFileName);
}
}
_wpfControl.ModelProvider.ObjectInstance = model;
} public void Clear()
{
if (_wpfControl.ModelProvider != null)
{
var currentIfcStore = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
currentIfcStore?.Dispose(); _wpfControl.ModelProvider.ObjectInstance = null;
}
}
}
}
 

xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览的更多相关文章

  1. xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览

    系列目录    [已更新最新开发文章,点击查看详细]  WPF应用程序在底层使用 DirectX ,无论设计复杂的3D图形(这是 DirectX 的特长所在)还是绘制简单的按钮与文本,所有绘图工作都是 ...

  2. C#将exe运行程序嵌入到自己的winform窗体中

    以下例子是将Word打开,然后将它嵌入到winform窗体中,效果如下图:C将exe运行程序嵌入到自己的winform窗体中 - kingmax_res - iSport注意:该方法只适用于com的e ...

  3. 关于WinForm引用WPF窗体---在Winform窗体中使用WPF控件

    项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...

  4. 在Winform窗体中使用WPF控件(附源码)

    原文:在Winform窗体中使用WPF控件(附源码) 今天是礼拜6,下雨,没有外出,闲暇就写一篇博文讲下如何在Winform中使用WPF控件.原有是我在百度上搜索相关信息无果,遂干脆动手自己实现. W ...

  5. 深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 3

    备注: 因为文章太长,所以将它分为三部分,本文是第三部分. 第一部分:深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 1 第二部分:深入浅出经典面试题:从浏览器中输入URL ...

  6. 从浏览器中输入URL到页面加载的发生了什么-转载

    转:https://www.cnblogs.com/confach/p/10050013.html 背景 “从浏览器中输入URL到页面加载的发生了什么“,这是一道经典的面试题,涉及到的知识面非常多,但 ...

  7. 【ASP.NET Core】EF Core - “影子属性” 深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 1

    [ASP.NET Core]EF Core - “影子属性”   有朋友说老周近来博客更新较慢,确实有些慢,因为有些 bug 要研究,另外就是老周把部分内容转到直播上面,所以写博客的内容减少了一点. ...

  8. Asp.Net Core 项目实战之权限管理系统(8) 功能菜单的动态加载

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  9. EXT中的iconCls 图标加载

    刚刚遇到了个奇怪的问题. 我用 在主页面用TAB autoLoad:{url:link, nocache: true, scripts:true} 加载页面Student.jsp, 郁闷,FF可以正常 ...

随机推荐

  1. hdoj--1251--统计难题(字典树)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Subm ...

  2. 【BZOJ 1878】 HH的项链

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1878 [算法] 显然,在线算法是不可做的,考虑离线算法 笔者的做法是莫队算法,时间复 ...

  3. USACO 2.2 Runaround Numbers

    Runaround Numbers Runaround numbers are integers with unique digits, none of which is zero (e.g., 81 ...

  4. 11.QT窗口布局切割

    int main(int argc, char *argv[]) { QApplication a(argc, argv); //MainWindow w; //w.show(); //左右分割 7 ...

  5. git工具的安装和使用

    啰嗦几句: 世界上本没有后悔药,但软件开发提供了后悔药,那就是代码管理工具.它可以让你的代码穿越回以前的状态,甚至可以指定某一个时刻,而且还可以穿越回来. 当下流行的代码管理工具有 SVN 和 GIT ...

  6. SQL学习——小结练习(1)

    到处淘来的SQL题 1. 用一条SQL 语句 查询出每门课都大于80 分的学生姓名 name   kecheng   fenshu 张三     语文       81张三     数学       ...

  7. 使用 Object.create实现js 继承

    二.Object.create实现继承 本文将来学习第七种继承方式Object.create()方法来实现继承,关于此方法的详细描述,请戳这里.下面来通过几个实例来学习该方法的使用: var Pare ...

  8. easyui的增删改

    陈旧的开发模式PM:“我要这个功能”后端:“这个先找前端做个模板”前端:“模板做完了”后端:“我来对接一下,这里样式不对”前端:“我改完了”后端:“功能交付”PM:“春节要加这个活动”后端:“这个先找 ...

  9. 安装Oracle 12c及解决遇到的问题

    一.[INS-30131]执行安装程序验证所需的初始设置失败(原因:无法访问临时位置) 原文链接:https://blog.csdn.net/u013388049/article/details/85 ...

  10. python 用法测试

    Python 3.5.6 1.js风格的回调测试 def b(): ') def a(fn): if callable(fn): fn() a(b) class Sample: def q(self) ...