Caliburn.micro - notifying a viewmodel on property

2019-07-21 07:47发布

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?

1条回答
来,给爷笑一个
2楼-- · 2019-07-21 08:29

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));
查看更多
登录 后发表回答