1

我目前正在尝试设计一个通过 MEF 导入加载视图模型的应用程序。

到目前为止一切顺利,我从 viewmodel 导航到 viewmodel,通过字典加载了每个 vm 数据模板。

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

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

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

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

谢谢你的帮助 !

[编辑]

加载字典:

<DataTemplate x:Shared="False" DataType="{x:Type vm:DAVPDC3DVIAControlViewModel}">
    <vw:MyUserControl />
</DataTemplate>

看法 :

<DockPanel>
    <ContentControl Name="WFH3DVia" Content="{Binding Path=Control3DVIA, Mode=OneWay} </ContentControl>"
    <!--<WindowsFormsHost Name="WFH3DVia"></WindowsFormsHost>-->
</DockPanel>

虚拟机(单例,mef 模块):

[Export(typeof(IDAVPDC3DVIAControl))]
public partial class DAVPDC3DVIAControlViewModel : ViewModelBase, IViewModel, IPartImportsSatisfiedNotification

虚拟机(主窗口)

[Export]
public class MainWindowViewModel : ViewModelBase, IPartImportsSatisfiedNotification

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

    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;
                    }
                }
            }
        }
    }
4

1 回答 1

1

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

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

现在,我了解了 DataBindings 的吸引力。相信我,我希望能够对 WindowForms 控件的许多部分进行 DataBind。当然,要接受 WPF 数据绑定,该属性必须是依赖对象上的依赖属性。最简单的解决方案,也不是不合理的,就是在你的视图后面的代码中简单地添加代码来配置你的窗体控件。将 UI 逻辑添加到 ViewModel 中实际上违反了 MVVM 设计模式,而在后面添加代码则不然。(在某些情况下是最好的方法)

我已经看到了试图绕过这个限制的可能的黑客攻击。包括使用注入数据绑定的“代理”,或者可能扩展 WindowsFormsHost 并添加包装特定托管控件属性的 DependencyProperties,或者使用反射编写类并尝试抛出 Windows 窗体绑定。但是,我所看到的任何东西都无法完全解决问题。例如,我的 windows 窗体控件可以包含其他图形组件,这些组件也需要支持绑定。

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

Last, let me comment more directly on your question. I would need to see how you are registering your View and ViewModel with the MEF Container and how you are navigating to understand why you are receiving that error. It would seem to me that either your view or view model is getting created more than once, while the other is not. Are these registered as singleton types? Regardless, I stand by what I said about not including the WindowsFormsHost in your ViewModel.

于 2012-10-12T04:27:35.527 回答