在WPF的MVVM模式中使用OCX组件

在WPF的MVVM模式中使用OCX组件

WPFMVVM模式中使用OCX组件

独立观察员 2018.09.11

OCX的正确使用姿势是在网页上使用,那么如果第三方只提供了OCX,我们在WPF程序中该如何调用呢?本文就来探讨该问题。

一、从OCX生成dll

按照《WPF 引用 OCX 控件 – CSDN 博客》的方法来:

1、先注册 OCX 控件;(有的把 OCX 控件封装到 EXE 文件中,安装即可);

2、打开 vs,新建一个 winform 程序,在工具箱中添加 COM 组件(把刚才注册的 OCX 控件)引用进来,这时就会看到当前 winform 程序 Debug 目录下会多出 2 个 DLL;

3、打开 vs,新建一个 WPF 程序,把上面的 2 个 DLL 引用上就可以了。

 

比如,我有一个 “TZ_SignMainDevOcx.ocx” 组件,经过以上方法,可得到以下两个文件:”AxInterop.TZ_SignMainDevOcxLib.dll” 和 “Interop.TZ_SignMainDevOcxLib.dll”。

 

二、添加到WPF项目中

我们要引用的是”AxInterop.TZ_SignMainDevOcxLib.dll”,”Interop.TZ_SignMainDevOcxLib.dll”是它的依赖项:

 

换言之,我们需要的方法都在带 “AxInterop” 前缀的dll中,而带 “Interop” 前缀的则是其依赖项。从图中还可以看出,实际要使用的类是在原OCX中的类前加上了 “Ax” 前缀。

 

三、MVVM方式调用

1、Xaml 添加一个隐藏的占位:

<ContentControl Grid.Row="1" Content="{Binding OcxContent}" Visibility="Collapsed"/>

 

2、ViewModel 中(使用AxTZ_SignMainDevOcx类):

// 绑定的对象
private object _ocxContent;
public object OcxContent
{
	get => _ocxContent;
	set => SetProperty(ref _ocxContent, value);
}

// 。。。

// 在主线程中实例化 com 组件
var axtz = new AxTZ_SignMainDevOcx();

// WPF 承载 windows 组件
System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
host.Child = axtz;

// 除了实例化 com 组件,还要将该对象进行初始化
((System.ComponentModel.ISupportInitialize)axtz).BeginInit();
OcxContent = new StackPanel
{
	Children = { host}
};
((System.ComponentModel.ISupportInitialize)axtz).EndInit();

// 调用
int ret = axtz.TZ_QrCodePrinter(0, "USB001", 0, 0, 5, info.barCode);

 

关键一点就是,除了要实例化相关对象,还要对其进行初始化。所以,如果是在Winform中使用,只要在 BeginInit 和 EndInit 之间,将实例化出的控件对象添加到界面中即可。

这里展示的是WPF的情况:

(1)要在主线程实例化相关对象,参见《当前线程不在单线程单元中, 因此无法实例化 ActiveX 控件的解决方案

(2)WPF 承载 windows 组件必须用 WindowsFormsHost(需引用WindowsFormslntegration),参见《WPF 中实例化 Com 组件,调用组件的方法时报 System.Windows.Forms.AxHost+InvalidActiveXStateException 的异常

(3)添加控件的方法我采用了MVVM的方式:Xaml中内容控件 ContentControl 的内容绑定了一个对象,然后新建一个StackPanel(或其它合适的容器)赋值给它,并将com组件的宿主(host)放在其中(赋值给Children),以此来完成初始化。

 

3、最后,就可以像调用普通方法一样调用了。

【转载请注明出处 Http://dlgcy.com】

打印本文

发表评论