MVVM Light Messenger 服务未在视图模型中接收消息
MVVM Light messenger service not receiving message in view model
不确定我是不是做错了,还是误解了堆栈溢出中的一些示例 here and here。
我正在尝试从我的第一个视图模型中获取选定的项目并将其传递到我正在导航到的另一个视图模型。这样做的目的是让我可以显示已通过的项目并允许用户使用它。
从第一个视图模型传递
这只是第一个视图模型的一小段。在这里,我首先导航到新的 page/view 模型。然后使用信使传递 SelectedRule 对象。导航是使用 ViewModelLocator class / MVVM Light 提供的导航服务完成的。
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 变量。
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;
}
}
已到达我的构造函数并设置了注册方法,但从未调用 GetMessage() 函数。我在这里错过了什么?
编辑
我将问题缩小到消息发送后正在调用 register 方法这一事实。现在我 运行 遇到的第二个问题是如何在发送前注册我的第二个视图模型?我在我的页面中使用视图模型定位器来确定每个页面的视图模型。即使我在发送数据之前执行 _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>
好的,所以我找到了解决问题的方法。我在导航之前使用我的 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 没有被用于任何东西,但它现在可以工作。
感谢您查看问题。
您需要等待页面出现后再发送消息。很奇怪,MVVMLight 没有像 Prism 那样提供任何 NavigateAsync 方法,所以你必须自己动手。
await Application.Current.Dispatcher.Invoke(
() => _navigationService.NavigateTo("UpdateBomRuleView");
ApprovedBomRule ruleToSend = SelectedRule; // Selected by user.
Messenger.Default.Send(ruleToSend);
根据我的 UWP 代码稍作修改,但对于 WPF 应该没问题。
不确定我是不是做错了,还是误解了堆栈溢出中的一些示例 here and here。
我正在尝试从我的第一个视图模型中获取选定的项目并将其传递到我正在导航到的另一个视图模型。这样做的目的是让我可以显示已通过的项目并允许用户使用它。
从第一个视图模型传递
这只是第一个视图模型的一小段。在这里,我首先导航到新的 page/view 模型。然后使用信使传递 SelectedRule 对象。导航是使用 ViewModelLocator class / MVVM Light 提供的导航服务完成的。
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 变量。
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;
}
}
已到达我的构造函数并设置了注册方法,但从未调用 GetMessage() 函数。我在这里错过了什么?
编辑
我将问题缩小到消息发送后正在调用 register 方法这一事实。现在我 运行 遇到的第二个问题是如何在发送前注册我的第二个视图模型?我在我的页面中使用视图模型定位器来确定每个页面的视图模型。即使我在发送数据之前执行 _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>
好的,所以我找到了解决问题的方法。我在导航之前使用我的 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 没有被用于任何东西,但它现在可以工作。
感谢您查看问题。
您需要等待页面出现后再发送消息。很奇怪,MVVMLight 没有像 Prism 那样提供任何 NavigateAsync 方法,所以你必须自己动手。
await Application.Current.Dispatcher.Invoke(
() => _navigationService.NavigateTo("UpdateBomRuleView");
ApprovedBomRule ruleToSend = SelectedRule; // Selected by user.
Messenger.Default.Send(ruleToSend);
根据我的 UWP 代码稍作修改,但对于 WPF 应该没问题。