将数据从窗口传递回ShellViewModel

时间:2018-01-28 21:27:45

标签: c# wpf caliburn.micro eventaggregator

好的,我遇到了解决这个问题的问题。我找到的大多数教程要么不完整,要么不能很好地解释这个过程。

我使用Caliburn.Micro创建了一个测试WPF应用程序,该应用程序的主窗口(ShellViewModel)有一个文本框和一个按钮,该按钮打开第二个窗口,其中包含一个文本框和另一个按钮。当用户在第二个窗口中添加文本并单击"发送" POCO对象已创建,应发送到第一个窗口并显示在ShellViewModel的文本框中。

我不确定我哪里出错,似乎没有很多文章可以帮助解决这个问题。

我尝试使用以下文章寻求帮助: https://claytonone.wordpress.com/2014/06/14/caliburn-micro-part-1-getting-started/

https://caliburnmicro.com/documentation/event-aggregator

******编辑 - 按照指示对上述项目进行了重新编程 https://caliburnmicro.com/documentation/event-aggregator 以下是该项目的代码。注意我添加了一个POCO类来存储和发送我想要发送到另一个窗口的数据,这更像是我在我正在进行的主要项目中的最终目标。

我现在遇到的问题: 1.当我运行本教程设计的程序时,VS Errored说没有无参数构造函数。为此,我尝试添加构造函数。现在程序运行了。 2.当我在第二个窗口中键入文本并单击发送时,我得到一个"空引用错误",如果我调试" ToSend"创建对象并使用正确的数据填充对象。 Error

AppBootStrapper:

namespace CaliburnMicro
{
    class AppBootstrapper : BootstrapperBase
    {
        private readonly SimpleContainer _container = new SimpleContainer();

        public AppBootstrapper()
        {
            Initialize();
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<ShellViewModel>();
        }

        protected override void Configure()
        {
            _container.Singleton<IEventAggregator, EventAggregator>();
        }
    }
}

ShellViewModel:

namespace CaliburnMicro.ViewModels
{
    class ShellViewModel : Screen, IHandle<EventMessage>
    {
        private string _messageBox;
        private readonly IEventAggregator _eventAggregator;


        public string MessageBox
        {
            get { return _messageBox; }
            set
            {
                _messageBox = value;
                NotifyOfPropertyChange(() => MessageBox);
            }
        }

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

        public ShellViewModel()
        {

        }

        public void OpenWindow()
        {
            WindowManager wm = new WindowManager();
            SecondWindowViewModel swm = new SecondWindowViewModel(_eventAggregator);
            wm.ShowWindow(swm);
        }

        public void Handle(EventMessage message)
        {
            MessageBox = message.Text;
        }
    }
}

SecondWindowViewModel

namespace CaliburnMicro.ViewModels
{
    class SecondWindowViewModel: Screen
    {

        private string _secondTextBox;
        private readonly IEventAggregator _eventAggregator;
        public EventMessage Tosend = new EventMessage();

        public string SecondTextBox
        {
            get { return _secondTextBox; }
            set
            {
                _secondTextBox = value;
                NotifyOfPropertyChange(() => SecondTextBox);
            }
        }



        public SecondWindowViewModel(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
        }

        public void SendBack()
        {
            Tosend.Text = SecondTextBox;
            _eventAggregator.PublishOnUIThread(Tosend);
            Thread.Sleep(1000); //I wanted the app to wait a second before closing
            TryClose();
        }

    }
}

这是我想要从第二个发送回主窗口的POCO。

namespace CaliburnMicro.Models
{
    class EventMessage
    {
        public string Text { get; set; }
    }
}

2 个答案:

答案 0 :(得分:1)

好的,这是一个关于如何使用AppBotstraper设置EventAggregator的小例子。

AppBootstrapper.cs

 public class AppBootstrapper : BootstrapperBase
{
    private SimpleContainer _container;

    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        _container = new SimpleContainer();
        _container.Singleton<IWindowManager, WindowManager>();
        _container.Singleton<IEventAggregator, EventAggregator>();
        _container.PerRequest<ShellViewModel>(); 
    }
    protected override object GetInstance(Type service, string key)
    {
        var instance = _container.GetInstance(service, key);
        if (instance != null)
            return instance;
        throw new InvalidOperationException("Could not locate any instances.");
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return _container.GetAllInstances(service);
    }

    protected override void BuildUp(object instance)
    {
        _container.BuildUp(instance);
    }

    protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
    {
        DisplayRootViewFor<ShellViewModel>();
    }
}

ShellViewModel.cs

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

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

    public void OpenWindow()
    {
        WindowManager wm = new WindowManager();
        SecondWindowViewModel swm = new SecondWindowViewModel(_eventAggregator);
        wm.ShowWindow(swm);
    }

    public void Handle(EventMessage message)
    {
        MessageBox.Show(message.Text);
    }
}

注意:如果您不了解Caliburn.Micro中的指挥,我建议您阅读this。当您使用指挥时,您可以使用ViewModel方法UserControl内的任何一个孩子ActivateItem开始。

您的SecondWindowViewModel保持不变,但EventMessage班级必须为public class EventMessage,否则您将收到错误。

答案 1 :(得分:0)

只是想一想,您是否设置了DataContext,以便您的主窗口知道ViewModel是您数据的来源?