【问题标题】:Caliburn.micro - notifying a viewmodel on property change in another viewmodelCaliburn.micro - 在另一个视图模型中通知视图模型的属性更改
【发布时间】:2014-10-06 17:53:30
【问题描述】:

我有一个连接到服务器并向其发送命令的程序。 在我的程序中,我有 2 个窗口,其中一个是带有显示当前状态的文本框的工具栏(我们称之为“mainviewmodel”),另一个是一个登录窗口,它接收用户名和密码并将我登录到服务器(我们称之为“登录视图模型”)

现在,为了让 mainviewmodel 知道 loginviewmodel 我使用这个:

[Import]
Private LoginViewModel loginViewModel;

从主视图模型午餐登录窗口我有以下功能:

public void Login()
{
    if (!loginViewModel.CanInvokeLogin)
        return;
    if (loginViewModel.IsActive)
    {
        loginViewModel.Focus();
    }
else
    {
        windowManager.ShowWindow(loginViewModel);
    }
}

如您所见 - 我在 loginviewmodel 中有一个名为 CanInvokeLogin 的属性,它指示登录是否正在进行。

在 mainviewmodel 上,我有一个显示当前客户端状态的属性(绑定到视图的文本框)

public string TextboxDescription
{
    get
    {
        switch (AvailabilityStatus.Type)
        {
            case AvailabilityStatusType.READY:
                return ("Ready");
            case AvailabilityStatusType.BREAK:
                return (AvailabilityStatus.Reason);
            case AvailabilityStatusType.DISCONNECTED:
                if (!loginViewModel.CanInvokeLogin)
                {
                    return ("Conencting");
                }
                return ("connected");
            default:
                return ("Please wait...");
            }
        }
    }
}

我的问题是 - 除非

,否则视图上的状态不会更新
NotifyOfPropertyChange(() => TextboxDescription);

正在被调用,所以我需要随时调用它

NotifyOfPropertyChange(() => CanInvokeLogin);

正在被调用,但这发生在不同的视图模型上。

那么,如何通知 mainviewmodel caninvokelogin 已更改? 我知道我可以使用 eventAggregator 并从一个视图模型向另一个视图模型发送消息,但这听起来像是用大炮杀死苍蝇,我敢打赌有一个更简单的方法,

有什么建议吗?

【问题讨论】:

  • 在这种情况下我会毫不犹豫地使用 eventtaggregator
  • 如果有对视图模型的引用,为什么?只需使用普通的旧 .NET 事件。
  • 聚合器有什么理由而不是像建议的那样注册事件?,eran?
  • 如果您在应用程序范围内广播某些内容,事件聚合器是一个不错的工具...例如,当用户退出应用程序时,或者如果有很多用户登录时,我可能会使用事件聚合器系统周围的其他类需要对此类事件做出反应。不过,在您给出的示例中,简单的旧事件是一个很好的解决方案......就像你说的......不要用大炮杀死苍蝇。
  • 最后我确实切换到使用 eventtaggregator - 使用事件导致我的程序爬行停止,突然随着每次断开和连接代表用户发送越来越多的 propertychange 事件,这可能是由于对于我写得不好的东西,所以我仍在测试它,但似乎使用 caliburn 消息优于使用事件,在这种情况下无论如何:)

标签: c# wpf mvvm viewmodel caliburn.micro


【解决方案1】:

处理属性更改事件

PropertyChanged 事件只是一个事件,因此如果您需要的话,没有什么能阻止您从另一个视图模型监听该事件。

this.loginViewModel.PropertyChanged += this.OnLoginPropertyChanged;

事件处理程序方法看起来像这样......

private void OnLoginPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "TextboxDescription") {
        // Do something.
    }
}

引发 StatusChanged 事件:

老实说,如果我自己实现这一点,我只会在状态更改时从 LoginViewModel 触发事件,然后改为处理这些事件,这似乎是一个更干净的解决方案。

this.loginViewModel.StatusChanged += this.OnLoginStatusChanged;

private void OnLoginStatusChanged(object sender, LoginStatusChangedEventArgs e)
{
    // Do something.
    switch (e.StatusType)
    {
        ...
    }
}

我会有这样的自定义事件参数...

public class LoginStatusChangedEventArgs : EventArgs
{
     public AvailabilityStatusType StatusType { get; set; }
}

当状态改变并且监听器可以处理时触发这个事件。

事件聚合器:

你也可以使用事件聚合器,但是除非你有很多不连贯的类需要听这个,否则我可能会觉得这有点矫枉过正。

this.eventAggregator.Publish(new LoginStatusChangedMessage(AvailabilityStatusType.Disconnected));

【讨论】:

  • 无法编辑并错过了其余的答案 :) 我不喜欢发布活动的想法,因为您不应该多次登录(或者如果出于某种原因您是无聊/QA,决定登录和注销很多次),我发布的代码只是需要的,其余的或多或少按照你的建议实现。
猜你喜欢
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 2011-07-04
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多