ShellViewModel 在 eventAggregator 上处理多条消息,Caliburn.Micro

ShellViewModel Handling multiple messages on the eventAggregator, Caliburn.Micro

我正在构建一个应用程序来帮助我学习 C#、WPF 和 .NET。在我的应用程序中,我正在为维修订单加载多个 CVS 会计数据表,每个 CVS 代表一个不同的时间表。使用 eventAggregator 效果很好。当用户按下 "load Schedule" 按钮时,另一个 window 打开,其中有一个 select 计划名称的下拉框,以及一个打开 "OpenFileDialoge" 框的按钮。在用户 select 都单击 "Load" 触发器“_eventAggregator.PublishOnUIThread(SchedInfo);”之后。 ShellViewModel 有一个 HAndle,它获取 Published "SchedInfo" 并将数据传递给另一个读取文件的函数 -> 构建每个 RepairOrder 并将它们添加到绑定到数据网格的维修订单的 BindableCollection。这非常有效。我现在的问题是我想创建第二个系统,它的工作原理相同,但读取 excel 文件并从中创建维修订单。我为要通过 eventAggregator 发送的 excel 消息创建了第二个 ViewModel、视图和 class。我还创建了一个全新的 "Handle(Message Class)" 来处理新的消息类型。但是我的新版本似乎没有将数据传回 "ShellViewModel" 或者 "ShellViewModel" 不接受数据。谁能看看我错在哪里了。

这是工作的 ViewModel 代码 window:

namespace ScheduleReview.ViewModels
{
    class SelSchedViewModel : Screen
    {
        /* System level properties */
        private readonly IEventAggregator _eventAggregator;
        List<string> folder = new List<string>();


        /* Class level properties*/

        private BindableCollection<string> _cmboBoxOptions = new BindableCollection<string>() { "Navistar", "Cummins", "Misc", "Kenworth", "Mack/Volvo" };

        public BindableCollection<string> CmboBoxOption
        {
            get { return _cmboBoxOptions; }
            set {
                _cmboBoxOptions = value;
                NotifyOfPropertyChange(() => CmboBoxOption);
            }
        }

        private string _scheduleName;

        public string ScheduleName
        {
            get { return _scheduleName; }
            set {
                _scheduleName = value;
                NotifyOfPropertyChange(() => ScheduleName);
            }
        }

        private string _fileLocation;

        public string FileLocation
        {
            get { return _fileLocation; }
            set {
                _fileLocation = value;
                NotifyOfPropertyChange(() => FileLocation);

            }
        }

        private string _fullLocation;

        public string FullLocation
        {
            get { return _fullLocation; }
            set {
                _fullLocation = value;
                NotifyOfPropertyChange(() => FullLocation);
            }
        }


        /* Constructor */
        public SelSchedViewModel(IEventAggregator eventAggregator)
        {
            this._eventAggregator = eventAggregator;
        }

        //Needs work still
        public void LoadSchedule()
        {
            if (folder.Contains(FileLocation))
            {
                MessageBox.Show("This file has already been used ", "Loaded File", MessageBoxButton.OK, MessageBoxImage.Error);
                ScheduleName = null;
                FileLocation = null;
                return;
            }

            //Create and set the class to return from
            //string file location and schedule number
            if(ScheduleName == null || FileLocation == null)
                {
                    MessageBox.Show("Enter the schedule name and choose a file location!", "Invalid Selections", MessageBoxButton.OK,MessageBoxImage.Error);
                }
                else
                {
                    ScheduleInfo SchedInfo = new ScheduleInfo(ScheduleName, FullLocation);
                    _eventAggregator.PublishOnUIThread(SchedInfo);
                    folder.Add(FileLocation);

                    ScheduleName = null;
                    FileLocation = null;

                }
            }

        public void SelectFile()
        {

            //Open the file selector box
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = Environment.SpecialFolder.MyDocuments.ToString();
            ofd.DefaultExt = ".csv";
            ofd.Filter = "CSV Documents (.CSV)|*.csv";

            Nullable<bool> result = ofd.ShowDialog();
            if (result == true)
            {
                FullLocation = ofd.FileName;
                char delimiter = '\';
                string[] NameArray = ofd.FileName.Split(delimiter);
                FileLocation = NameArray[NameArray.Count() - 1];
            }
        }

        //Closes Window
        public void Close()
        {
            TryClose();
        }
    }
}

这是正在运行的 ShellViewModel 中的句柄:

public void Handle(ScheduleInfo message)
        {
            ScheduleName = message.ScheduleName;
            FileInfo = message.FileLocation;
            LoadSchedule(ScheduleName, FileInfo);
        }

这是从工作加载程序传递到 ShellViewModel 的 POCO class 的代码:

namespace ScheduleReview.Models
{
    public class ScheduleInfo
    {
        public string ScheduleName
        {
            get;
            private set;
        }

        public string FileLocation
        {
            get;
            private set;
        }

        public ScheduleInfo(string SN, string FL)
        {
            ScheduleName = SN;
            FileLocation = FL;
        }
    }
}

现在我实际上复制并粘贴了 window 设计和弹出的第一个 ViewModel 中的大部分 ViewModel。为新加载程序 window 创建了新消息 class 并更改了新 window 中的部分以匹配新消息 class.

新Loader的ViewModel代码为:

namespace ScheduleReview.ViewModels
{
    class SelCDKSchedViewModel : Screen
    {
        /* System level properties */
        private readonly IEventAggregator _eventAggregator;
        List<string> folder = new List<string>();


        /* Class level properties*/

        private BindableCollection<string> _cmboBoxOptions = new BindableCollection<string>() { "Navistar", "Cummins", "Misc", "Kenworth", "Mack/Volvo" };

        public BindableCollection<string> CmboBoxOption
        {
            get { return _cmboBoxOptions; }
            set
            {
                _cmboBoxOptions = value;
                NotifyOfPropertyChange(() => CmboBoxOption);
            }
        }

        private string _scheduleName;

        public string ScheduleName
        {
            get { return _scheduleName; }
            set
            {
                _scheduleName = value;
                NotifyOfPropertyChange(() => ScheduleName);
            }
        }

        private string _fileLocation;

        public string FileLocation
        {
            get { return _fileLocation; }
            set
            {
                _fileLocation = value;
                NotifyOfPropertyChange(() => FileLocation);

            }
        }

        private string _fullLocation;

        public string FullLocation
        {
            get { return _fullLocation; }
            set
            {
                _fullLocation = value;
                NotifyOfPropertyChange(() => FullLocation);
            }
        }


        /* Constructor */
        public SelCDKSchedViewModel(IEventAggregator eventAggregator)
        {
            this._eventAggregator = eventAggregator;
        }

        //Needs work still
        public void LoadSchedule()
        {
            if (folder.Contains(FileLocation))
            {
                MessageBox.Show("This file has already been used ", "Loaded File", MessageBoxButton.OK, MessageBoxImage.Error);
                ScheduleName = null;
                FileLocation = null;
                return;
            }

            //Create and set the class to return from
            //string file location and schedule number
            if (ScheduleName == null || FileLocation == null)
            {
                MessageBox.Show("Enter the schedule name and choose a file location!", "Invalid Selections", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            else
            {
                CDKScheduleInfo CDKSchedInfo = new CDKScheduleInfo(ScheduleName, FullLocation);
                _eventAggregator.PublishOnUIThread(CDKSchedInfo);
                folder.Add(FileLocation);

                ScheduleName = null;
                FileLocation = null;

            }
        }

        public void SelectFile()
        {

            //Open the file selector box
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = Environment.SpecialFolder.MyDocuments.ToString();
            ofd.DefaultExt = ".xlsx";
            ofd.Filter = "XLSX Documents (.XLSX)|*.xlsx";

            Nullable<bool> result = ofd.ShowDialog();
            if (result == true)
            {
                FullLocation = ofd.FileName;
                char delimiter = '\';
                string[] NameArray = ofd.FileName.Split(delimiter);
                FileLocation = NameArray[NameArray.Count() - 1];
            }
        }

        //Closes Window
        public void Close()
        {
            TryClose();
        }
    }
}

新加载程序的句柄代码window:

public void Handle(CDKScheduleInfo message)
        {
            ScheduleName = message.ScheduleName;
            FileInfo = message.FileLocation;
            ReadFromCDKExport(ScheduleName, FileInfo);
        }

Poco class 不工作加载 window。

class CDKScheduleInfo
    {
        public string ScheduleName
        {
            get;
            private set;
        }

        public string FileLocation
        {
            get;
            private set;
        }

        public CDKScheduleInfo(string SN, string FL)
        {
            ScheduleName = SN;
            FileLocation = FL;
        }

    }

根据我的阅读,Caliburn.Micro 的 eventAggregator 实现允许 "Handles" 使用多态性,所以我觉得两个句柄接受不同的 Class 对象,因为我应该工作。

作为测试,我注释掉了 NOT working handle "ReadFromCDKExport(ScheduleName, FileInfo);" 中的行,因此 public 变量 "ScheduleName" 和 "FileInfo" 将被设置,然后我连线要显示的测试按钮:

MessageBox.Show(ScheduleName + Environment.newline + FileInfo, "Test", MessageBoxButton.OK);

会弹出消息框,但消息中没有变量。

--------------------根据 Royi 的回答编辑-------------------- ----------

我忘记将 IHandle 接口添加到 Class。

eventAggregator 使用接口 IHandle 来计算多态性,

您可能忘记了将 CDKScheduleInfo 接口的 IHandle 添加到 ShellViewModel :)