如果 II 只是没有弄清楚实际的方法,我深表歉意,但我已经浏览了各种博客文章并且觉得离答案更近了。
我正在编写一个 WP7 应用程序,它本质上是一个将时间转换为成本的秒表。
该模型包含方法 Start() 和 Pause() 以及双重属性 Cost。在 ViewModel 中,我将 ICommands 用于 Start() 和 Pause(),这会触发底层模型函数。然而,在调用 Start() 之后,我希望 UI 能够反映成本的增加。
我考虑了几种方法:
- ViewModel 通过一个自我实现的订阅者模型订阅模型,并且模型在模型运行时每隔几毫秒通知所有订阅者。
- View Model StartCommand 启动一个后台工作程序,该工作程序每隔几毫秒在 Cost 属性上触发一个 RaisePropertyChanged 事件。
我选择了第二个建议,因为模型根本不需要线程(它只记录用户按下开始和暂停的时间,并在成本计算中使用它)。我的方法基于http://msdn.microsoft.com/en-us/library/cc221403(VS.95).aspx
但是,当我尝试运行它时,我得到一个“UnauthorizedAccessException”。代码如下:
Backgroundworker 在构造函数中被创建为 VM 成员
public MeetingCostViewModel()
{
_backgroundWorker = new BackgroundWorker
{
WorkerSupportsCancellation = true,
WorkerReportsProgress = false,
};
_backgroundWorker.DoWork += DoWork;
}
StartCommand 触发后台工作者运行
private DelegateCommand _startCommand;
public ICommand StartCommand
{
get
{
return _startCommand ?? (_startCommand = new DelegateCommand(
delegate
{
_meetingCost.Start();
_keepUpdating = true;
if (_backgroundWorker.IsBusy != true)
{
_backgroundWorker.RunWorkerAsync();
}
}));
}
}
这是基于http://blog.lab49.com/archives/1166的实际工作方法
private void DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
PropertyChangedEventHandler temp = PropertyChanged;
if (temp != null)
{
temp(this, new PropertyChangedEventArgs("Cost"));
}
Thread.Sleep(50);
}
}
我不确定这是否是正确的方法,但我想保持 View 数据绑定并且没有“代码隐藏”,但是这里的大多数替代响应都需要明确设置控件,我想不惜一切代价避免。