我首先在C#/ WPF / Entity Framework DB中编写一个应用程序,它与专有的工业硬件通信,可以测量冷却液管路中的流量和温度等值。这些值经常在我的SQL Server数据库中使用在后台运行的线程更新,然后显示在我的UI中。
我目前关注的是如何更新我的UI以反映这些更改。以下是我如何更新数据网格的示例:
我将我的datacontext设置为我的viewmodel,并实例化一个每秒运行一次的线程:
_DataContext = new ViewModels.SummaryTable_ViewModel();
this.DataContext = _DataContext;
UIUpdateThread = new Thread(UIUpdaterThread);
UIUpdateThread.IsBackground = true;
UIUpdateThread.Start();
我的网格基于的模型是IList<>看起来像这样:
private IList<channel> _channel;
public IList<channel> Channels
{
get
{
return _channel;
}
set
{
_channel = value;
//NotifyPropertyChanged();
OnPropertyChanged("Channels");
}
}
然后我的UIUpdateThread每秒调用我的FillChannels()方法,如下所示,然后根据propertychanged通知更新网格:
using (var DTE = new myEntities())
{
if (DTE.channels.Any())
{
var q = (from a in DTE.channels
where a.setup.CurrentSetup == true
orderby a.ChannelNumber
select a).ToList();
this.Channels = q;
}
}
所以我的问题是:有更好,更优雅的方式吗?由于缺乏更好的术语,这感觉“错误”。它有不好的副作用,比如每次线程运行时重置我的数据网格上的用户设置排序。另外我认为它打破了MVVM模式,虽然我不确定。
例如,我正在考虑如果与我的硬件对话的线程在每次轮询硬件数据时更新共享的Channel对象,我只是将我的UI绑定到它,这样我就不用运行了这个线程(或我的其他UI上的其他线程做同样的事情),只是基于PropertyChanged通知进行更新。还是有其他方法我完全没有意识到?在寻找答案时,我看到了工作单元模式的提及,我不熟悉,这是一个相关的概念吗?
正如你所看到的,我不太确定从哪里开始,可以真正使用一些帮助。对不起文字墙,我只想尽可能彻底。任何帮助将不胜感激。感谢。
答案 0 :(得分:4)
我认为您的模型应该是在有新数据时通知您的视图模型的模型。您应该将完成此操作的任何机制(例如我假设您正在使用的计时器)放入模型中。
基本上,您的模型会通知您的视图模型,并且您的视图模型会通知视图存在数据更改。如果您正确设置视图 - 并使用XAML而不是代码隐藏,则它们应该通过视图和视图模型之间的数据绑定自动组合在一起。
关于排序:它应该是视图模型的一个单独属性,它绑定到视图网格上的排序属性。您的模型应该维护用户设置的排序,并在更新数据时通知视图模型之前将其适当地应用于更新的数据。
我不确定工作单元是否适用于此处,因为您并未讨论将相关的数据行保存到多个表并将其作为一个事务执行 - 您只是在阅读数据。我可能错了,因为我还没有那么多地研究工作单元。
在评论中解决您的问题:
让我们后退一步。您的视图模型应仅关注与相关视图的呈现相关的逻辑。它不应该有任何数据访问代码或代码执行任何业务逻辑或域相关的任务;该代码进入了统称为&#34;模型&#34; (如果您已经拥有此功能,请原谅我,但很难准确说出您在问题中提供的代码所在的位置)。
该模型可以包含许多类,这些类执行不同的业务逻辑任务或代表您的域/实体POCO(如您的实体框架生成的类)。
我有点不清楚你的Channel
对象是什么以及它与你的实体类/ POCO是如何分开的,即EF生成的模型。但同样,您与EF的交互以及与您的实体相关的维护和逻辑应该在模型中发生。
所以是的,想法是你使用你想要的任何机制在模型中寻找数据变化 - 例如一个计时器(顺便说一下,计时器是同步运行的,所以不要将&#34;计时器&#34;与#34;线程&#34;)的概念混为一谈,或直接绑定到&#34;收集更改& #34;您的实体集合上的事件。检测到更改时,您只需在模型中执行该更改所需的任何业务逻辑(如应用转换,排序,日志记录等),然后通知视图模型已发生更改。