Как дочерняя ViewModel предлагает родительской ViewModel перейти в Caliburn.Micro? - PullRequest
0 голосов
/ 17 мая 2019

В Caliburn.Micro у меня есть Shell ViewModel, которая имеет 3 свойства IShell, соответствующие 3 элементам управления содержимым в связанном представлении.Это «Полный», «Список» и «Деталь».«Полный» расположен выше двух других и имеет такую ​​же ширину, как и форма хоста.«Список» находится слева на 1 строку вниз, а «Сведения» - в той же строке, что и столбец «Список» 1 справа.

При запуске приложения ViewModel для входа в систему привязывается к «Полный»и ничто не связано с двумя другими.На экране отображается только экран входа в систему.Пользователь должен войти в систему, а после завершения «Полный» элемент управления контентом должен переключиться с отображения ViewModel входа на AccountViewModel.

Для этого мне нужно, чтобы LoginViewModel сообщал ShellViewModel (его родительский элемент) о необходимости навигации.в AccountViewModel.

Как мне это сделать?

public class ShellViewModel : Screen
{
    #region Fields

    private string _title = "License Manager";

    private Conductor<IScreen> _fullFrameConductor;
    private Conductor<IScreen> _listFrameConductor;
    private Conductor<IScreen> _detailFrameConductor;

    #endregion

    public ShellViewModel()
    {
        _fullFrameConductor = new Conductor<IScreen>();
        _listFrameConductor = new Conductor<IScreen>();
        _detailFrameConductor = new Conductor<IScreen>();

        FullFrame = Framework.GetContainer().Resolve<LoginViewModel>();            
    }

    #region Properties

    public string Title { get => _title; set => _title = value; }

    public IScreen FullFrame
    {
        get { return _fullFrameConductor.ActiveItem; }
        set {
            _fullFrameConductor.ActivateItem(value);
            NotifyOfPropertyChange(nameof(FullFrame));
        }
    }

    public IScreen ListFrame
    {
        get { return _listFrameConductor.ActiveItem; }
        set {
            _listFrameConductor.ActivateItem(value);
            NotifyOfPropertyChange(nameof(ListFrame));
        }
    }

    public IScreen DetailFrame
    {
        get { return _detailFrameConductor.ActiveItem; }
        set {
            _detailFrameConductor.ActivateItem(value);
            NotifyOfPropertyChange(nameof(DetailFrame));
        }
    }


    #endregion

    #region Commands

    public void ShowProducts()
    {
        ListFrame = Framework.GetContainer().Resolve<ProductListViewModel>();
        DetailFrame = Framework.GetContainer().Resolve<ProductViewModel>();
    }

    public void ShowLicenses()
    {
        ListFrame = Framework.GetContainer().Resolve<LicenseListViewModel>();
        DetailFrame = Framework.GetContainer().Resolve<LicenseViewModel>();
    }


    #endregion
}


public class LicenseViewModel : Screen
{

    public void Login()
    {
        // This should process the login and then tell the Shell it is done
        // then the shell should navigate to the Account ViewModel sharing
        // the user info with the AccountViewModel via a memory cache

        // How do I alert the screen ViewModel causing it to close this viewmodel
        // without causing a threading problem?
    }
}

1 Ответ

0 голосов
/ 17 мая 2019

Вы можете использовать Event Aggregator для связи между LoginViewModel и ShellViewModel. Вы можете прочитать больше об Event Aggregator здесь.

Во-первых, вам нужно создать класс сообщений

public class AuthenticationSuccessMessage
{
    public bool IsValidLogin{get;set;}
}

Затем следующим шагом будет использование EventAggregator для уведомления ShellViewModel из LicenseViewModel.

private IEventAggregator _eventAggregator;
 public LicenseViewModel (IEventAggregator eventAggregator) 
 {
    _eventAggregator = eventAggregator;
 }

 public void Login()
 {
    _eventAggregator.PublishOnUIThread(new AuthenticationSuccessMessage{IsValidLogin=true});
 }

Последний шаг - подписка на события в ShellViewModel.

public class ShellViewModel:Screen, IHandle<AuthenticationSuccessMessage>
{
   private readonly IEventAggregator _eventAggregator;

   public ShellViewModel:Screen(IEventAggregator eventAggregator) {
        _eventAggregator = eventAggregator;
        _eventAggregator.Subscribe(this);
    }
    void Handle<AuthenticationSuccessMessage>(AuthenticationSuccessMessage message)
    {
        if(message.IsValidLogin)
        {
            // Do Task
        }
    }
}

Подробнее об агрегаторах событий можно прочитать здесь .

Обновление : не забудьте подписаться на агрегатор событий в ShellViewModel.

...