c# - 如何正确使用在 C++/CLI 中实现的类作为 .net 中数据绑定(bind)的数据源?

标签 c# .net c++-cli

我在 VC++ 中定义了一个抽象类,如下所示:

public ref class AbstractFoo abstract {
public:
   virtual property String^ Bar {
       virtual String^ get() = 0;
   }

   // More stuff
};

我有多个像这样的具体类:

public ref class ConcreteFoo : AbstractFoo {
public:
    property String^ Bar {
        virtual String^ get() override;
    }
    // more
}

我现在想在 C# 应用程序的 ComboBox 中选择多个 AbstractFoo 实现之一。因此,我单击组合框上的小箭头并选中“使用数据绑定(bind)项”。然后,我尝试使用 AbstractFoo 类型创建一个新数据源。然后单击 Finish 时,我得到:

Error using the dropdown: Object reference not set to an instance of an object.

当我关闭对话框时,VS 退出。当我使用 ConcreteFoo 时也会发生这种情况。

目前,我能想到的唯一可行的解​​决方案是在 C# 中定义一个类,如下所示:

internal sealed class FooWrapper {

    private readonly AbstractFoo _foo;

    internal FooWrapper(AbstractFoo foo) {
        _foo = foo;
    }

    public String DisplayName { get { return _foo.Bar; } }

    public static implicit operator AbstractFoo(FooWrapper w) {
        return w._foo;
    }
}

然后添加这些 FooWrappers 并使用隐式转换来获取 AbstractFoo

这真的是唯一的方法吗?还是我在 VS 阻塞的地方声明了错误?

编辑:在创建 GUI 时,ConcreteFoo 实现已经存在。

最佳答案

我对此进行了更多调查,并找到了导致此问题的原因。据我目前所知,除了上述解决方法外,没有其他解决方案。

它与托管/非托管互操作有关。我在这个项目中仍然绑定(bind)到 VS2010,所以我不知道这只是其中的一个错误还是我的错误配置。

这是我重现该行为的方式:

首先,我创建了一个 C++/CLI 类库,其中包含一个非常简单的抽象类和具体类(我们暂时称它们为 AbstractThingConcreteThing)。然后,我创建了一个简单的 C# Windows 窗体应用程序,其中仅包含一个组合框,该组合框使用 AbstractThing 绑定(bind)到绑定(bind)源。类型。这奏效了。

然后我像往常一样将依赖项添加到非托管库:将非托管库的包含目录指定为附加包含目录,该目录包含 unmanaged.libunmanaged.dll对于调试和 Release模式,并添加 unmanaged.lib作为附加库。然后,我在 C# 应用程序中添加了一个构建后命令,用于复制适当的 unmanaged.dll成功构建后进入构建目录。

重新创建绑定(bind)仍然有效。

现在,进入游戏破坏者:

一旦我向非托管库添加了一个包含,如 #include <unmanaged.h>我得到了上面的错误并且 VS 退出了。

为了解决问题,我随后创建了一个如上所述的包装器,它起初有效,但导致了下一个奇怪的错误:当我重新进入 GUI 设计器时,我得到了一个我管理的错误页面/unmanaged interop DLL(包含 AbstractThingConcreteThing 的那个)找不到。案例是:.net 的数据绑定(bind)分析公共(public)属性的类,如果它们中的任何一个碰巧属于与非托管内容互操作的类型,事情就会变得疯狂。我相信 GUI 设计器和 VS 在错误的目录中查找依赖的非托管 DLL。

因此,唯一可行的方法是编写一个包装器并通过使用内部属性或方法显式地进行提取来隐藏数据绑定(bind)中的互操作内容。

所以,这个例子的包装器 AbstractThing类现在工作:

internal sealed class ThingWrapper {

    private readonly AbstractThing _thing;

    internal ThingWrapper(AbstractThing thing) {
        _thing = thing;
    }

    public String DisplayName { get { return _thing.SomeStringProperty; } }

    internal AbstractThing Thing { get { return _thing; } }
}

制作internal AbstractThing Thing属性(property)public导致设计器无法正确加载,因此无法使用 ValueMember绑定(bind)源的属性。自 AbstractThing theThing = ((ThingWrapper) theComboBox.SelectedItem).Thing; 起必须手动完成提取

关于c# - 如何正确使用在 C++/CLI 中实现的类作为 .net 中数据绑定(bind)的数据源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32992334/

相关文章:

.net - 如何在 XAML 中填充 List<string>?

sorting - cli C++ 对某个属性的对象列表进行排序

visual-studio-2008 - 线程 'Win32 Thread'已退出,代码为-1073740777(0xc0000417)

.net - 编译器错误 C2440

c# - 别名示例,尝试理解这个问题

c# - 将二维数组上的两个循环转换为 Linq 语法

c# - INotifyPropertyChanged 的​​ PropertyChanged 事件处理程序背后是什么?消息接收/处理机制是什么?

c# - 欧拉角增量超过 360 度

c# - 您的数据访问类是什么样的?

c# - Visual Studio : Setting a conditional breakpoint without setting an unconditional one first