在MVVM Light中获取UserControl的当前ViewModel

本文关键字:ViewModel UserControl 获取 MVVM Light | 更新日期: 2023-09-27 18:00:15

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

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

但是,由于UserControl可以根据其当前所在的View与任何ViewModel关联,我如何从后面的UserControl代码中获得正确的ViewModel

在MVVM Light中获取UserControl的当前ViewModel

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

GamePageViewModel MyControlViewModel = MyControl.DataContext as GamePageViewModel;

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

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

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

这些方法是由@Fruchtzberg和@mechtich提出的。我只是想澄清一下

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

(正如你的帖子所建议的,所有代码都在后面的用户控制代码中)

一堆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)并从中继承视图模型(以及VMBase从MVVMLight ViewModelBase继承?)

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