MVVM Light Messenger服务未在视图模型中接收消息

时间:2018-12-10 21:46:36

标签: wpf viewmodel mvvm-light

不确定我是做错了还是误解了堆栈上herehere上已经出现的一些示例。

我试图从我的第一个视图模型中获取一个选定的项目,并将其传递给我要导航到的另一个视图模型。这样做的目的是让我可以显示已通过的项目,并允许用户使用它。

从第一视图模型传递

这只是第一视图模型的一小段。在这里,我首先导航到新的页面/视图模型。然后使用Messenger传递SelectedRule对象。导航是使用MVVM Light随附的ViewModelLocator类/导航服务完成的。

private ApprovedBomRule _selectedRule = new ApprovedBomRule();

public ApprovedBomRule SelectedRule
{
    get { return _selectedRule;}
    set { Set(ref _selectedRule, value); }
}

private void NavigateToUpdateRule()
{
    //Navigate to Update Rule page
    _navigationService.NavigateTo("UpdateBomRuleView");
    //Pass selected rule as a parameter using messenger service
    ApprovedBomRule ruleToSend = SelectedRule; // Selected by user.
    Messenger.Default.Send(ruleToSend);
}

在接收视图模型时

这是我的第二个视图模型,在该模型中,我从上方注册了相同类型的SelectedRule并将其设置为公共变量。

public class UpdateBomRuleViewModel : ViewModelBase
{
    private ApprovedBomRule _passedRule;

    public ApprovedBomRule PassedRule
    {
        get => _passedRule;
        set => Set(ref _passedRule, value);
    }
    //Constructor
    public UpdateBomRuleViewModel()
    {
        //Register message type
        Messenger.Default.Register<ApprovedBomRule>(this, GetMessage);
    }
    //Set the property to passed object
    public void GetMessage(ApprovedBomRule rule)
    {
        PassedRule = rule;
    }
}

到达我的构造函数并设置了register方法,但从未调用GetMessage()函数。我在这里想念什么?

编辑

我将问题缩小到发送消息后正在调用register方法的事实。现在,我遇到的第二个问题是在发送之前如何注册第二个视图模型?我在页面中使用viewmodel定位器来确定每个页面的视图模型。即使我在发送数据之前执行_navigation.NavigateTo(),也要等到发送之后才初始化视图模型。

页面中的视图模型定位器示例

<local:BasePage x:Class="YAI.BomConfigurator.Desktop.Views.Rules.UpdateBomRuleView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:YAI.BomConfigurator.Desktop"
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800"
  Title="UpdateBomRuleView"
  DataContext="{Binding UpdateBomRuleViewModel, Source={StaticResource Locator}}">

<Grid>
    <TextBlock Text="{Binding PassedRule.Description}" 
               VerticalAlignment="Center"
               HorizontalAlignment="Center">

    </TextBlock>
</Grid>

2 个答案:

答案 0 :(得分:0)

好的,所以我找到了解决该问题的方法。我在导航之前使用ServiceLocator来获取实例。

 var vm = ServiceLocator.Current.GetInstance<UpdateBomRuleViewModel>();
 //Navigate to Update Rule page
 _navigationService.NavigateTo("UpdateBomRuleView");
 //Pass selected rule as a parameter using messenger service
 ApprovedBomRule ruleToSend = SelectedRule; // Selected by user.
 Messenger.Default.Send(ruleToSend);

这导致我的寄存器在发送之前被调用。我不一定喜欢这种解决方案,因为var vm并未用于任何用途,但目前可以使用。

感谢您查看问题。

答案 1 :(得分:0)

在发送消息之前,您需要等待页面显示出来。奇怪的是,MVVMLight没有提供任何像Prism这样的NavigateAsync方法,因此您必须自己滚动。

await Application.Current.Dispatcher.Invoke( 
    () => _navigationService.NavigateTo("UpdateBomRuleView");

ApprovedBomRule ruleToSend = SelectedRule; // Selected by user.
Messenger.Default.Send(ruleToSend);

从我的UWP代码中稍作修改,但是对于WPF应该没问题。