【问题标题】:MVVM Light messenger message not received from Command未从 Command 收到 MVVM Light messenger 消息
【发布时间】:2020-03-16 11:54:47
【问题描述】:

我正在使用 MVVM Light 框架构建 WPF 应用程序。

我正在尝试打开一个窗口并将一些信息(即一个对象)传递给这个新创建的 ViewModel。

我有一个 WPF 窗口 (MainListView/MainListViewModel),它有一个绑定到对象列表的 ListBox:

<ListBox ItemsSource="{Binding Selected_Agent.Associated_Letter, Mode=OneWay}"
         SelectedItem="{Binding Selected_Letter, Mode=TwoWay}">
<!-- More code below -->

在MainListView我还有一个绑定到命令的按钮:

<Button Content="Update" Command="{Binding UpdateCommand}"/>
private ICommand _updateCommand;
public ICommand UpdateCommand
{
    get
    {
        if (_updateCommand == null)
        {
            _updateCommand = new RelayCommand(_windowService.OpenWindow<AddNewLetterView>, UpdateCommand_CanExecute());
            Messenger.Default.Send(new UpdateLetterMessage() { Letter = Selected_Letter });
        }
        return _updateCommand;
    }
}

这会打开一个新窗口,AddNewLetterView 使用 AddViewLetterViewModel,它由 MVVM Light 的 ViewModelLocator 链接。

在AddNewLetterViewModel 构造函数中我这样做:

public AddNewLetterViewModel()
{
    Messenger.Default.Register<UpdateLetterMessage>(this, UpdateLetterMessageReceived);
}

问题是没有收到此消息。即使视图打开,UpdateLetterMessageReceived 上的断点也不会被命中。

如果我在命令上设置断点,则在单击按钮时,它永远不会被命中,AddNewLetterViewMdoel 上的 UpdateLetterMessageReceived 也不会被命中,即使 AddNewLetterView 已打开。

似乎正在发生的事情是在 MainListViewModel 实例化期间调用了一次 UpdateCommand,这意味着在实例化 AddNewLetterViewModel 之前发送了消息。

正确吗?如果是这样,我如何确保在调用命令时发送我的消息?

如果没有,这里发生了什么,我该如何实现?

【问题讨论】:

    标签: wpf mvvm mvvm-light


    【解决方案1】:

    你的更新命令应该是这样的:

        private ICommand _updateCommand;
    
        public ICommand UpdateCommand
        {
            get
            {
                if (_updateCommand == null)
                {
                    _updateCommand = new RelayCommand(() =>
                    {
                        _windowService.OpenWindow<AddNewLetterView> ();
                        Messenger.Default.Send(new UpdateLetterMessage() {Letter = Selected_Letter});
                    }, UpdateCommand_CanExecute);
                }
                return _updateCommand;
            }
        }
    

    你有它的方式,它只是在第一次创建命令时发送消息,我相信你想在命令执行时发送它

    顺便说一句,我发现这种命令结构更有帮助。让它看起来像一个普通的方法

    public ICommand UpdateCommand => _updateCommand ?? (_updateCommand = new RelayCommand(() =>
    {
        _windowService.OpenWindow<AddNewLetterView> 
        Messenger.Default.Send(new UpdateLetterMessage() {Letter = Selected_Letter});
    }, UpdateCommand_CanExecute));
    

    为了更清楚,你的函数是这样做的:

        private ICommand _updateCommand;
    
        public ICommand UpdateCommand
        {
            get
            {
                if (_updateCommand == null)
                {
                    _updateCommand = new RelayCommand(DoSomething, CanDoSomething);
                    Messenger.Default.Send(etc); <=====THIS SHOULD BE....
                }
                return _updateCommand;
            }
        }
    
    public void DoSomething()
    {
        _windowService etc
        <=====.....HERE
    }
    
    public bool CanDoSomething() {}
    

    我使用的 () => {} 表示法是定义函数 DoSomething 的简写

    【讨论】:

    • 谢谢蒂姆,这完全符合我的需要。老实说,我不太明白有什么区别。在实例化/执行时触发 _updateCommand = new RelayCommand(); 和 _updateCommand = new RelayCommand(() =&gt; { }); 有什么不同?
    • 你传入RelayCommand的第一个参数的,是命令执行时执行的代码。 () => {} 允许你定义多行代码,而不仅仅是一个函数
    • 在创建命令时调用 messenger.send 调用,而不是在执行命令时调用。
    • 啊,太棒了!这已经说得很清楚了。我缺少的是 RelayCommand 的 DoSomething 参数。有时,速记版本会让人更难理解实际发生的事情以及调用的内容和时间。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 2019-05-11
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多