子视图不会自动实例化它们的“视图模型”

Posted

技术标签:

【中文标题】子视图不会自动实例化它们的“视图模型”【英文标题】:Child views do not instantiate their 'View-Models' automatically 【发布时间】:2012-07-25 22:16:31 【问题描述】:

我在 PRISM 架构中有一个 WPF 应用程序。

我有一个用户控件(视图),里面有 2 个用户控件。

Here is the idea :

“搜索用户控件”之所以在其自己的用户控件中,是因为我计划在我的应用程序中重用它。

主用户控件 (black) 称为“MainView”,其中包含 2 个用户控件: - 一个用户控件,它有几个我可以过滤的文本框控件和一个“搜索”按钮 - 一个用户控件,它有一个显示结果的网格

每个用户控件(以及父级“主视图”)都是“视图”并具有“视图模型”。

一切都很好,除了“子”用户控件不会自动创建自己的“视图模型”。

在视图模型的类中,我有 'Export' 属性, 在 View 的代码隐藏中,我有这个 sn-p:

[Import]
FilterFieldsViewModel ViewModel
           
    set
    
       this.DataContext = value;
    

设置“视图模型”确实发生在“主视图”中,但不适用于子视图...

我有一个绑定到“搜索用户控件”的“搜索”按钮的命令, 当应用程序加载时 - 我在输出窗口中收到一个错误,说:

BindingExpression 路径错误:在“对象”“MainWindowViewModel”(HashCode=22047425)上找不到“SearchCommand”属性。绑定表达式:路径=搜索命令; DataItem='MainWindowViewModel' (HashCode=22047425);目标元素是“按钮”(名称=“搜索”);目标属性是“Command”(输入“ICommand”)

出于某种原因,来自“子”用户控件的命令尝试绑定到主窗口视图模型中的视图模型,因为出于某种原因 - 子用户控件的视图模型未实例化。

这是为什么?

【问题讨论】:

【参考方案1】:

您的依赖注入容器 (MEF) 未在子视图上注册导入,因为它们是由 MainView 而不是 MEF 创建的。您可能想要做的是在您的 MainViewModel 上创建一个属性:

[Import]
public FilterFieldsViewModel FilterFieldsViewModel get; set; 

然后在 XAML 中:

<UserControl ....>
   ...
   <SearchUserControl DataContext="Binding FilterFieldsViewModel" ... />
   ...
</UserControl>

这使 MEF 能够为您创建 FilterFieldsViewModel 的实例并将其发送到 SearchUserControl

这当然是基本概念,也许您想创建一个“SearchViewModelBase”或具有FilterFieldsViewModel 的东西。

【讨论】:

很好的解决方案,只有一个问题 - 这不是将主视图与子视图结合起来吗? 我在某处读到一个可能的解决方案可能是为“搜索控件”定义一个区域和为“网格控件”定义一个区域,然后使用 MEF 将控件自动加载到这些地区。这种方法的问题在于,在设计过程中 - 我将无法看到最终的“主”窗口中包含控件的样子......你明白吗? @JohnMiner 你确实是正确的,从架构的角度来看,定义子区域是一个更好的解决方案,但它需要更多的工作,所以我想这更像是一个“财务”决定。 ***.com/questions/4818840/… 这个问题应该提供一些关于作用域子区域的信息。

以上是关于子视图不会自动实例化它们的“视图模型”的主要内容,如果未能解决你的问题,请参考以下文章

Android MVVM:无法实例化视图模型

以编程方式实例化自定义视图控制器并通过标签获取子视图

必须使用延迟实例化的UI视图将子视图添加到视图控制器两次

实例化 Nib 并访问它的子视图

用户默认值不会实例化视图控制器

如何在 UWP 中实例化具有构造函数的页面?