系列目录 [已更新最新开发文章, 点击查看详细]
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 = -1;
- 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[0] 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 = -1;
- }
- }
- /// <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(0, 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;
- }
- }
- }
- }
系列目录 [已更新最新开发文章, 点击查看详细]
来源: https://www.cnblogs.com/SavionZhang/p/11011870.html