Caliburn.micro-在另一个视图模型中向视图模型通知属性更改 [英] Caliburn.micro - notifying a viewmodel on property change in another viewmodel

查看:141
本文介绍了Caliburn.micro-在另一个视图模型中向视图模型通知属性更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



现在,为了使mainviewmodel知道loginviewmodel,我使用了以下方法:

  [导入] 
私人LoginViewModel loginViewModel;

从mainviewmodel插入登录窗口我具有以下功能:

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

您可以看到-我在loginviewmodel中有一个属性



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

 公共字符串TextboxDescription 
{
get
{
开关(AvailabilityStatus.Type)
{
case AvailabilityStatusType.READY:
return( Ready);
情况AvailabilityStatusType。BREAK:
返回(AvailabilityStatus.Reason);
case AvailabilityStatusType.DISCONNECTED:
if(!loginViewModel.CanInvokeLogin)
{
return( Conencting);
}
返回(已连接);
默认值:
return( Please wait ...);
}
}
}
}

我的问题是-除非

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

被调用,所以我需要在


$ b时调用它$ b

  NotifyOfPropertyChange(()=> CanInvokeLogin); 

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



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



有什么建议吗?

解决方案

处理财产变更事件



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

  this.loginViewModel.PropertyChanged + = this.OnLoginPropertyChanged; 

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

  private void OnLoginPropertyChanged(对象发送者,PropertyChangedEventArgs e)
{
if(e.PropertyName == TextboxDescription){
// 做一点事。
}
}

提高状态更改的事件:



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

  this.loginViewModel.StatusChanged + = this.OnLoginStatusChanged; 

私有无效OnLoginStatusChanged(对象发送者,LoginStatusChangedEventArgs e)
{
//做点事情。
开关(e.StatusType)
{
...
}
}

我会像这样自定义事件args ...

 公共类LoginStatusChangedEventArgs: EventArgs 
{
public AvailabilityStatusType StatusType {get;组; }
}

仅在状态更改且侦听器可以处理此事件时触发此事件。 / p>

事件聚合器:



不过,您也可以使用事件聚合器,除非您有许多断开连接的类需要听这个,我可能会觉得这太过头了。

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


I have a program that connects to a server and sends commands to it. in my program I have 2 windows, one of them is a toolbar with a textbox that shows current status (we'll call that "mainviewmodel") and the other is a login window which receives username and password and logs me into the server (we'll call that "loginviewmodel")

now, in order for the mainviewmodel to know the loginviewmodel I use this:

[Import]
Private LoginViewModel loginViewModel;

lunch the login window from the mainviewmodel I have the following function:

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

as you can see - I have in loginviewmodel a property named CanInvokeLogin which indicates if login is in progress or not.

on mainviewmodel I have a property that shows me current client status (binded to the view's textbox)

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...");
            }
        }
    }
}

My problem is - the status would not be updated on the view unless

NotifyOfPropertyChange(() => TextboxDescription);

is being called, so I need to call it whenever

NotifyOfPropertyChange(() => CanInvokeLogin);

is being called, but that happens on a different viewmodel.

so, how can I notify the mainviewmodel that caninvokelogin have been changed? I know I could use eventAggregator and send a message from one viewmodel to another, but it sounds like killing a fly with a cannon and I bet there's a simpler way,

any suggestions?

解决方案

Handle The Property Changed Event

The PropertyChanged event is simply an event so there is nothing stopping you from listening to that event from another view model if that is what you need.

this.loginViewModel.PropertyChanged += this.OnLoginPropertyChanged;

The event handler method would look something like this...

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

Raise StatusChanged Events:

To be honest if I was implementing this myself I would simply be firing events from the LoginViewModel when the status changed and then handling those events instead, seems like a cleaner solution to this.

this.loginViewModel.StatusChanged += this.OnLoginStatusChanged;

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

I would have custom event args like so...

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

Just fire this event when the status changes and listeners can handle that.

Event Aggregator:

You could also use the event aggregator however unless you have lots of disconnected classes that need to listen to this I would probably feel it was overkill.

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

这篇关于Caliburn.micro-在另一个视图模型中向视图模型通知属性更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆