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. 英语发音规则---G字母

    英语发音规则---G字母 一.总结 一句话总结: 1.G发[g]音? bag [bæg] n. 袋:猎获物 go [gəʊ] vi. 走:达到 garden ['gɑːd(ə)n] n. 花园 gla ...

  2. [JavaEE] Maven简介

    转载自:百度 http://baike.baidu.com/view/336103.htm?fr=aladdin 一.简介 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构 ...

  3. htmlunit 简单操作

    首先我们新建一个Maven普通客户端项目,然后打开pom.xml 引入htmlunit支持: <dependency> <groupId>net.sourceforge.htm ...

  4. 深入了解React组件重新渲染的条件和生命周期

    React组件rerender的真正条件 当前组件的State中的属性改变时且当前组件的shouldcomponentupdate返回true,那么当前组件会rerender 组件的props中的任一 ...

  5. ddk安装失败后的处理

    7600.16385.1版本的DDK,在xp的本上死活按不上,怎么办呢?自己就把其他机器上安装的DDK目录,拷贝过来. 怎么建编译环境呢? 查看x86 Checked Build Environmen ...

  6. Unity 向量点乘、叉乘

    向量点乘计算角度,向量叉乘计算方位 a,b为向量 点乘计算公式:a x b = |a| x |b| x cosθ 叉乘计算公式:a x b = |a| x |b| x sinθ

  7. 从源码中查看当前android版本

    从文件build/core/version_defaults.mk查找PLATFORM_VERSION例如:PLATFORM_VERSION.OPM1 := 8.1.0

  8. LeetCode Golang 7. 整数反转

    7. 整数反转 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. Tips : Math包给出的类型大小的边界: // Integer limit values. const ...

  9. Pyhton学习——Day48

    # 转载:http://www.cnblogs.com/yuanchenqi/articles/6437362.html#python关于mysql的API--pymysql模块# 执行sql语句# ...

  10. IOS - IOS之同步请求、异步请求、GET请求、POST请求(转载)

    转载:http://www.open-open.com/lib/view/open1355055986679.html 1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务 ...