Caliburn.micro - уведомление модели представления об изменении свойства в другой модели представления

У меня есть программа, которая подключается к серверу и отправляет ему команды. в моей программе у меня есть 2 окна, одно из них представляет собой панель инструментов с текстовым полем, которое показывает текущий статус (мы назовем это «mainviewmodel»), а другое — окно входа в систему, которое получает имя пользователя и пароль и регистрирует меня на сервере ( мы назовем это "loginviewmodel")

теперь, чтобы mainviewmodel знала модель входа в систему, я использую это:

[Import]
Private LoginViewModel loginViewModel;

обед окно входа в систему из mainviewmodel у меня есть следующая функция:

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 и отправить сообщение из одной модели просмотра в другую, но это звучит как убийство мухи из пушки, и я уверен, что есть более простой способ,

какие-либо предложения?


person Koby Yehezkel    schedule 13.08.2014    source источник
comment
Я бы демонстративно использовал агрегатор событий в этом сценарии.   -  person eran otzap    schedule 13.08.2014
comment
Зачем, если есть ссылка на модель представления? Просто используйте обычные старые события .NET.   -  person BenjaminPaul    schedule 13.08.2014
comment
Любая причина для агрегатора, а не для подписки на события, подобные предложенным?   -  person Koby Yehezkel    schedule 13.08.2014
comment
Агрегатор событий - хороший инструмент, если вы транслируете что-то в масштабе приложения... Я бы, возможно, использовал агрегатор событий, когда пользователь выходит из приложения, например, или, возможно, когда он входит в систему, если многие другие классы в системе должны реагировать к таким событиям. Однако в приведенном вами примере простые старые события - хорошее решение... как вы сказали... не убивайте муху из пушки.   -  person BenjaminPaul    schedule 13.08.2014
comment
В конце концов я переключился на использование агрегатора событий - использование событий привело к тому, что моя программа остановилась, внезапно с каждым отключением и подключением от имени пользователя было отправлено все больше и больше событий изменения свойств, это может быть связано с чем-то, что я написал плохо, поэтому я Я все еще тестирую его, но кажется, что использование сообщений caliburn лучше, чем использование событий, в любом случае в этом случае :)   -  person Koby Yehezkel    schedule 14.08.2014


Ответы (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));
person BenjaminPaul    schedule 13.08.2014
comment
Не могу отредактировать и пропустил остальную часть ответа :) Мне не нравится идея публикации событий, так как вы не должны входить в систему более одного раза (или если по какой-то причине вам скучно/QA и вы решаете войти и выйти из системы много раз раз), опубликованный мной код - это только то, что нужно, остальное реализовано более-менее так, как вы предложили. - person Koby Yehezkel; 13.08.2014