【问题标题】:MVVM Light Message not received when sending from ViewModel constructor从 ViewModel 构造函数发送时未收到 MVVM 轻消息
【发布时间】:2013-10-26 12:25:05
【问题描述】:

我遇到了以下问题:

我正在使用 ViewModelLocator 中的 SimpleIoc 注册 4 个 ViewModel。 在 MainViewModel 的构造器中,我向其他 3 个 ViewModel 中的 2 个发送消息。 这些 ViewModel 不会收到这些消息。

消息本身是有效的,因为当我稍后在这些 ViewModel 上发送消息时,它们会按预期做出反应。

所以我希望接收 ViewModel 在我从 MainViewModel 构造函数发送消息时没有监听。所以我切换了我用 SimpleIoc 注册 ViewModel 的顺序,但无济于事。

我做错了什么?

ViewModelLocator

    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<LoginMethodVM>();
        SimpleIoc.Default.Register<DatabaseConnDataVM>();
        SimpleIoc.Default.Register<UserCredentialsVM>();
        SimpleIoc.Default.Register<BrowserSelectionVM>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public LoginMethodVM LoginMethodVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<LoginMethodVM>();
        }
    }

    public DatabaseConnDataVM DatabaseConnDataVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<DatabaseConnDataVM>();
        }
    }

    public UserCredentialsVM UserCredentialsVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<UserCredentialsVM>();
        }
    }

    public BrowserSelectionVM BrowserSelectionVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<BrowserSelectionVM>();
        }
    }

MainViewModel

    public MainViewModel()
    {
        Messenger.Default.Send(System.Windows.Visibility.Visible, "UserCredentialsVisible");
        Messenger.Default.Send(System.Windows.Visibility.Visible, "BrowserSelectionVisible");
    }

BrowserSelectionVM

    public BrowserSelectionVM()
    {
        Messenger.Default.Register<System.Windows.Visibility>
            (this,
            "BrowserSelectionVisible",
            msg => { Visible = msg; });

    }

UserCredentialsVM

    public UserCredentialsVM()
    {
        Messenger.Default.Register<System.Windows.Visibility>
            (this,
            "UserCredentialsVisible",
            msg => { Visible = msg; });
    }

【问题讨论】:

  • 当您从 MainViewModel 发送消息时,这些视图模型是否已实例化
  • 我的直觉是接收器不是,但我无法分辨,改变顺序也无济于事。
  • 所以,如果你还没有在内存中创建视图模型的实例,那么Register命令就不会运行,所以没有任何东西注册来接收消息。试试这个,在 MainViewModel 构造函数调用发送之前,创建每个视图模型的实例。 SimpleIOC 与这个问题无关,因为它所做的只是注入到您的视图模型中,并且您的视图模型中没有构造函数参数可以注入。
  • ViewModels 是由 ServiceLocator...GetInstance 创建的,我猜是在注册 VieModel 时调用的。
  • 不,只有在创建视图模型的实例后才会创建视图模型,方法是直接在某处的代码中打开它们的实例 (UserCredentialVM test = new UserCredential();),或者通过他们通过打开一个视图来使用视图模型定位器,其中视图模型是 XAML 中的数据上下文 (DataContext="{Binding UserCredentialVM, Source={StaticResource Locator}}")。 ServiceLocator 不会自动创建视图模型的实例。只需在正在注册的 View Model 的构造函数中放置一个断点,以查看它在调用发送消息之前没有被注册。

标签: c# wpf mvvm mvvm-light


【解决方案1】:

ViewModelLocator.cs

    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<UserCredentialsVM>(true);
        SimpleIoc.Default.Register<BrowserSelectionVM>(true);
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public UserCredentialsVM UserCredentialsVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<UserCredentialsVM>();
        }
    }

    public BrowserSelectionVM BrowserSelectionVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<BrowserSelectionVM>();
        }
    }

    public MainViewModel MainViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public static void Cleanup()
    {
    }

BrowserSelectionVM.cs

public class BrowserSelectionVM : ViewModelBase
{
    public BrowserSelectionVM()
    {
        Messenger.Default.Register<System.Windows.Visibility>(this,
            "BrowserSelectionVisible",
            msg => { Console.WriteLine(msg); });
    }
}

UserCredentialsVM.cs

public class UserCredentialsVM : ViewModelBase
{
    public UserCredentialsVM()
    {
        Messenger.Default.Register<System.Windows.Visibility>(this,
            "UserCredentialsVisible",
            msg => { Console.WriteLine(msg); });
    }
}

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        Messenger.Default.Send(System.Windows.Visibility.Visible, "UserCredentialsVisible");
        Messenger.Default.Send(System.Windows.Visibility.Visible, "BrowserSelectionVisible");
    }
}

MainWindow.xaml

<Window x:Class="MvvmLightRegistrationMock.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">

<Grid x:Name="LayoutRoot">
</Grid>

【讨论】:

  • 我看不出有什么不同。
  • @MPL 我无法重现您所看到的内容。在我的测试环境中,我能够看到两条可见消息。我已经更新了我的答案并发布了我的测试环境中的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多