【问题标题】:Get info from another window in Caliburn.Micro, WPF, MVVM从 Caliburn.Micro、WPF、MVVM 中的另一个窗口获取信息
【发布时间】:2018-12-08 18:58:21
【问题描述】:

我正在基于 Caliburn.Micro mvvm 框架在我的应用程序中制作登录窗口。那么,如何从由 Caliburn.Micro 初始化的登录窗口中的TryClose() 方法返回一个属性(例如,true,如果用户传递了良好的数据或false,如果他传递了错误的凭据)?如何从IWindowManager.ShowDialog()打开的窗口获取信息?

首先,我的 MainWindowViewModel.cs

using Caliburn.Micro;

namespace TaskManager.ViewModels
{
    class MainWindowViewModel : Conductor<IScreen>.Collection.OneActive
    {
        protected override void OnViewLoaded(object view)
        {
            IWindowManager manager = new WindowManager();
            //Login page, context is data with user's lists
            LoginViewModel loginView = new LoginViewModel(context);
            manager.ShowDialog(loginView, null, null);
            //here i want to get info, if i get logged properly or not
        }

        public void LoadUserInfoPage() //here starts "main" program
        {
            ActivateItem(new UserInfoViewModel());
        }
        //and so on...
    }

}

我的LoginViewModel.cs

namespace TaskManager.ViewModels
{
class LoginViewModel : Screen
{
    public string Login    { get; set; }
    public string Password { get; set; }

    public LoginViewModel(FakeData context)
    {
        this.context = context;
    }

    public void LoginButton()
    {
        bool check = Services.Login.IsValid(Login, Password, context);
        if(check) //if login is OK, check == true
            TryClose();
    }

    private FakeData context { get; set; } //data is here
}
}

那么,我的IsValid()方法:

namespace TaskManager.Services
{
static class Login
{
    static public bool IsValid(string login, string password, FakeData context) 
        => context.users.Any(i => i.Login == login);
        //i know it is bad, but its only example
}
}

按钮,打开和关闭窗口效果很好(也可以从文本框中读取)。如果用户传递了良好的数据,我只想获取信息(也许通过参考?)。

感谢您的建议!

【问题讨论】:

    标签: c# wpf mvvm caliburn.micro


    【解决方案1】:

    您可以为此目的使用 EventAggregator。

    “事件聚合器是一种提供发布能力的服务 对象以松散的方式从一个实体到另一个实体。 "

    第一步是在您的 ViewModel 中创建 EventAggregator 实例并订阅它。您可以通过两个 ViewModel 的构造函数中的 DI 来完成。

    对于 LoginViewModel,

    private IEventAggregator _eventAggregator;
    public LoginViewModel(FakeData context,IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }
    

    还有 MainWindowViewModel,

    private IEventAggregator _eventAggregator;
    public MainWindowViewModel (IEventAggregator eventAggregator)
    {
    _eventAggregator = eventAggregator;
    _eventAggregator.Subscribe(this);
    }
    

    下一步是创建一个消息对象,它可以在 ViewModel 之间传输所需的信息。

    public class OnLoginAttemptMessage
    {
        string UserName { get; set; }
        bool IsLoginSuccessful { get; set; }
    }
    

    最后,是时候把所有东西放在一起了。在 LoginViewModel 中的你的 LoginButton 方法中,我们修改代码以在成功登录时引发事件。

    public void LoginButton()
    {
      bool check = Services.Login.IsValid(Login, Password, context);
      if(check) //if login is OK, check == true
      {
        _eventAggregator.PublishOnUIThread(new OnLoginAttemptMessage
        {
          UserName = Login,
          IsLoginSuccessful = check;
        });
        TryClose();
       }
     }
    

    最后一步是在MainWindowViewModel中,这里需要实现IHandle接口。

    class MainWindowViewModel : Conductor<IScreen>.Collection.OneActive, IHandle<OnLoginSuccessMessage>
    {
    
            public void Handle(OnLoginSuccessMessage message)
            {
                if(message.IsLoginSuccessful)
                {
                    // Login is successfull, do next steps.
                }
            } 
    }
    

    您可以在此处阅读有关 EventAggregator 的更多信息 (https://caliburnmicro.com/documentation/event-aggregator)

    【讨论】:

    • 我可以像这样转移任何我想要的东西吗?字符串、整数等?
    • 是的,你可以。您在消息类中定义的任何结构都可以转移
    • 嗨,我在 Caliburn.micro 上发布了另一个问题。如果你能看一下我会很高兴:D stackoverflow.com/questions/53706176/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多