C# MVVM MEF WindowFormHost

C# MVVM MEF WindowFormHost,c#,wpf,mvvm,mef,C#,Wpf,Mvvm,Mef,我目前正在尝试设计一个通过MEF导入加载viewmodels的应用程序 到目前为止还不错,我通过字典加载了每个vm数据模板,从一个viewmodel导航到另一个viewmodel 每次导航时,我都会在Shell(主窗口)中修改主contentPresenter的内容 其中一个viewmodel允许我为activeX控件(例如acrobat reader)显示WindowFormHost。由于WindowFormHost不允许绑定,我在viewmodel中创建了WindowFormHost,并将其

我目前正在尝试设计一个通过MEF导入加载viewmodels的应用程序

到目前为止还不错,我通过字典加载了每个vm数据模板,从一个viewmodel导航到另一个viewmodel

每次导航时,我都会在Shell(主窗口)中修改主contentPresenter的内容

其中一个viewmodel允许我为activeX控件(例如acrobat reader)显示WindowFormHost。由于WindowFormHost不允许绑定,我在viewmodel中创建了WindowFormHost,并将其绑定到视图中的ContentPresenter

这就是它失败的地方:当返回到同一个viewmodel时,会再次创建视图。。。抛出一个“元素已经是另一个元素的子元素。”错误

我怎样才能防止呢?重新加载视图时是否应卸载WindowFormHost?或者我可以保留视图实例,以便每个视图只保留一个实例,并让数据绑定更新控件吗?(它看起来更适合内存消耗)

谢谢你的帮助

[编辑]

已加载字典:

<DataTemplate x:Shared="False" DataType="{x:Type vm:DAVPDC3DVIAControlViewModel}">
    <vw:MyUserControl />
</DataTemplate>
虚拟机(主窗口)

//CurrentUC将主窗口视图绑定到控制器活动视图模型

    public IViewModel CurrentUC
    {
        get
        {
            return myAddinManager.CurrentVM;
        }
    }
主要观点:

控制器(事件时显示模块):


我还在WPF中使用Prism v4和MVVM处理一个项目(除了使用Unity)。我还需要使用至少两个控件,它们是必须托管在WindowsFormsHost中的Windows窗体控件。让我解释一下我对这个过程的看法

在我看来,您正在试图避免视图的代码隐藏中的任何代码。这是我能想到的将WindowsForms移到ViewModel中的唯一原因。我认为这根本是错误的做法。WindowsFormsHost的存在是为了显示图形化Windows窗体控件。因此,它属于视图

现在,我明白了数据绑定的吸引力。相信我,我一直希望能够对WindowForms控件的许多部分进行数据绑定。当然,要接受WPF数据绑定,该属性必须是依赖项对象上的依赖项属性。最简单的解决方案(并非不合理)是在代码隐藏中添加代码来配置windows窗体控件以供查看。将UI逻辑添加到ViewModel中实际上违反了MVVM设计模式,而添加代码隐藏则不是。(在某些情况下是最好的方法)

我见过可能的黑客试图绕过这个限制。包括使用插入数据绑定的“代理”,或者扩展WindowsFormsHost并添加封装特定托管控件属性的DependencyProperties,或者使用反射编写类并尝试插入windows窗体绑定。然而,我所看到的一切都不能完全解决这个问题。例如,我的windows窗体控件可以包含其他图形组件,这些组件也需要支持绑定

最简单的方法是简单地将视图与视图代码中的viewmodel同步。视图模型可以保留打开的文件或文档、文件名、标题等,但将显示和与显示相关的控件留给视图


最后,让我更直接地谈谈你的问题。我需要了解您是如何向MEF容器注册视图和ViewModel的,以及您是如何导航的,以了解您收到该错误的原因。在我看来,视图或视图模型被创建了不止一次,而另一个没有。这些是否已注册为单例类型?无论如何,我支持我所说的不在ViewModel中包含WindowsFormsHost的观点。

我还在WPF中使用Prism v4和MVVM进行一个项目(使用Unity除外)。我还需要使用至少两个控件,它们是必须托管在WindowsFormsHost中的Windows窗体控件。让我解释一下我对这个过程的看法

在我看来,您正在试图避免视图的代码隐藏中的任何代码。这是我能想到的将WindowsForms移到ViewModel中的唯一原因。我认为这根本是错误的做法。WindowsFormsHost的存在是为了显示图形化Windows窗体控件。因此,它属于视图

现在,我明白了数据绑定的吸引力。相信我,我一直希望能够对WindowForms控件的许多部分进行数据绑定。当然,要接受WPF数据绑定,该属性必须是依赖项对象上的依赖项属性。最简单的解决方案(并非不合理)是在代码隐藏中添加代码来配置windows窗体控件以供查看。将UI逻辑添加到ViewModel中实际上违反了MVVM设计模式,而添加代码隐藏则不是。(在某些情况下是最好的方法)

我见过可能的黑客试图绕过这个限制。包括使用插入数据绑定的“代理”,或者扩展WindowsFormsHost并添加封装特定托管控件属性的DependencyProperties,或者使用反射编写类并尝试插入windows窗体绑定。然而,我所看到的一切都不能完全解决这个问题。例如,我的windows窗体控件可以包含其他图形组件,这些组件也需要支持绑定

最简单的方法是简单地将视图与视图代码中的viewmodel同步。视图模型可以保留打开的文件或文档、文件名、标题等,但将显示和与显示相关的控件留给视图

最后,让我更直接地谈谈你的问题。我需要了解您是如何向MEF容器注册视图和ViewModel的,以及您是如何导航的,以了解您收到该错误的原因。在我看来,e
[Export(typeof(IDAVPDC3DVIAControl))]
public partial class DAVPDC3DVIAControlViewModel : ViewModelBase, IViewModel, IPartImportsSatisfiedNotification
[Export]
public class MainWindowViewModel : ViewModelBase, IPartImportsSatisfiedNotification
    public IViewModel CurrentUC
    {
        get
        {
            return myAddinManager.CurrentVM;
        }
    }
    private void ModuleReadyEventAction(string iModuleName)
    {
        if (null != this.Modules && this.Modules.Count() > 0)
        {
            foreach (var item in Modules)
            {
                IBaseModule ibasemodule = item as IBaseModule;
                if (null != ibasemodule)
                {
                    Type tp = ibasemodule.GetType();
                    if (0 == tp.Name.CompareTo(iModuleName))
                    {
                        CurrentVM = ibasemodule.GetViewModel();
                        break;
                    }
                }
            }
        }
    }