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 :)
我正在构建一个应用程序来帮助我学习 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 :)