【问题标题】:Get the current ViewModel for a UserControl in MVVM Light在 MVVM Light 中获取 UserControl 的当前 ViewModel
【发布时间】:2016-12-10 13:15:36
【问题描述】:

我有一个UserControl,用于多个Views。每个View 都有自己的ViewModel。我知道我可以从它后面的代码中获取UserControl 的当前ViewModel 使用

GamePageViewModel viewModel = ServiceLocator.Current.GetInstance<GamePageViewModel>();

但是,由于UserControl 可以与基于当前启用的View 的任何ViewModel 相关联,我如何从UserControl 后面的代码中获取正确的ViewModel?

【问题讨论】:

  • 我是否正确理解您的 UserControl 没有自己的视图模型,而是使用托管 UserControl 的任何视图中的视图模型?
  • 没错。它使用托管它的任何 View 的 ViewModel。

标签: c# mvvm user-controls win-universal-app mvvm-light


【解决方案1】:

只需在后面的代码中调用控件的 DataContext。假设您有 UserControl 类型的实例 MyControl,并且您想要它的 ViewModel 实例 MyControlViewModel 类型为 GamePageViewModel。在这种情况下,您可以使用

GamePageViewModel MyControlViewModel = MyControl.DataContext as GamePageViewModel;

【讨论】:

  • 这是否意味着如果当前视图模型不是GamePageViewModel,MyControlViewModel 将返回null?
  • 完全正确,如果这是一个问题,你应该创建一个类 BaseViewModel 并从这个 BaseViewModel 派生 GamePageViewModel。然后您可以将 DataContext 转换为 BaseViewModel 广告,并将其与不同的派生 ViewModel 一起使用。
  • 我确实有一个 BaseViewModel,但是当我将它转换为 GamePageViewModel 时,它仍然返回 NULL。 UserControl 的 ViewModel 是 GamePageViewModel。 BaseViewModel currenVM = this.DataContext as BaseViewModel; if ((GamePageViewModel)currenVM != null) { viewModel = currenVM as GamePageViewModel; }
  • 如果您不知道自己获得的是哪个 ViewModel,请继续使用 currenVM,而不要将其转换为 GamePageViewModel。
  • 我需要访问 GamePageViewModel 中的属性,这些属性在 BaseViewModel 中不可用,因此使用 currentVM 而不进行强制转换会产生错误。
【解决方案2】:

如果您需要访问可与UserControl 一起使用的所有 ViewModel 的一些通用属性,请指定一个接口(或另一个基类)并将DataContext 强制转换为该接口。

但是,通常直接指定UserControl 的DataContext 是个坏主意。如果您想将一些上下文传递给UserControl,请使用here 所述的依赖属性(请参阅Use dependency properties to pass parameters to a view 部分) .

【讨论】:

  • 谢谢。如果我可以将公共属性移动到基类,这是一个好主意。但只是想知道如何通过后面的代码获取托管 UserControl 的 View 的 ViewModel。
【解决方案3】:

您可以简单地询问控件本身的 DataContext。代码将向上搜索依赖关系树,直到找到数据上下文(应该是托管页面的 ViewModel) 根据您设计 ViewModel 的方式,您可以通过多种不同的方式处理它。这里有一些可能对您有用,或者可能需要您重新设计。

这些方法是由@Fruchtzwerg 和@mechanic 提出的。我只是想帮助澄清一下。

似乎还有其他选项不涉及从代码后面询问视图模型,但没有说明您的代码的目的。

(正如您的帖子所建议的,所有代码都在用户控件代码隐藏中)

一堆 if/then 语句(可能最不受欢迎)

    if (DataContext is ViewModelA)
    {
        var _vm = (ViewModelA)DataContext;
        _vm.DoViewModelAMethod();
        _vm.Property1 = "abc";
    }
    else if (DataContext is ViewModelB)
    {
        var _vm = (ViewModelB)DataContext;
        _vm.DoViewModelBMethod();
        _vm.Property1 = "abc";
    }
    //etc. etc.

将常用方法/属性移动到基类(此处称为 VMBase)并从中继承您的视图模型(以及从 MVVMLight ViewModelBase 继承的 VMBase?)

    var _vm = DataContext as VMBase;
    if(_vm != null)
    {
        _vm.DoViewModelMethod();
        _vm.Property1 = "abc";
    }

如果您正在使用通用方法/属性的不同实现,请使用和接口并让视图模型实现接口。

    var _vm = DataContext as IVMBase;
    if(_vm != null)
    {
        _vm.DoViewModelMethod();
        _vm.Property1 = "abc";
    }

【讨论】:

    猜你喜欢
    • 2013-05-31
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    相关资源
    最近更新 更多