c# - 如何在数据库更改时更新 WPF UI

标签 c# wpf multithreading mvvm datagrid

我首先使用 C#/WPF/Entity Framework DB 编写一个应用程序,该应用程序与一个专有的工业硬件通信,该硬件测量来自冷却剂管线的流量和温度等值。这些值经常通过在后台运行的线程在我的 SQL Server 数据库中更新,然后显示在我的 UI 中。

我目前关心的是如何更新我的用户界面以反射(reflect)这些变化。下面是我如何更新数据网格的示例:

我将我的数据上下文设置为我的 View 模型,并实例化一个每秒运行的线程:

    _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 绑定(bind)到它,这样我就不必运行这个线程(或我其他用户界面上做同样事情的其他线程),只是根据 PropertyChanged 通知进行更新。还是有其他我完全不知道的方法?在寻找答案时,我看到提到了我不熟悉的工作单元模式,这是一个相关的概念吗?

如您所见,我不太确定从这里该往哪里走,真的需要一些帮助。对不起,文字墙,我只是想尽可能彻底。任何帮助将不胜感激。谢谢。

最佳答案

我认为您的模型应该是在有新数据时通知您的 View 模型的模型。您应该将实现此目的的任何机制(例如我假设您正在使用的计时器)放入模型中。

基本上,您的模型会通知您的 View 模型,而您的 View 模型会通知 View 有数据更改。如果您正确地设置了您的 View ——并使用 XAML 而不是代码隐藏,那么它们应该通过 View 和 View 模型之间的数据绑定(bind)自动组合在一起。

关于排序:这应该是 View 模型的一个单独属性,它绑定(bind)到 View 网格上的排序属性。您的模型应该维护用户设置的排序,并在数据更改时通知 View 模型之前将其适本地应用于更新的数据。

我不确定这里是否适用工作单元,因为您不是在谈论将相关的数据行持久保存到多个表并将其作为一个事务来执行——您只是在读取数据。不过我可能是错的,因为我还没有深入研究工作单元。


在评论中解决您的问题:

让我们退一步。您的 View 模型应该关注与关联 View 的表示相关的逻辑。它不应该有任何数据访问代码或执行任何业务逻辑或领域相关任务的代码;该代码进入统称为“模型”的部分(如果您已经有了这个,请原谅我,但很难准确地说出您在问题中提供的代码所在的位置)。

该模型可以由许多类组成,这些类执行不同的业务逻辑任务或代表您的域/实体 POCO(例如您的 Entity Framework 生成的类)。

我有点不清楚您的 Channel 对象是什么以及它如何与您的实体类/POCO(即 EF 生成的模型)分开。但同样,您与 EF 的交互以及与您的实体相关的维护和逻辑应该发生在模型中。

所以是的,我们的想法是您使用您想要的任何机制来查找模型中的数据变化——例如计时器(顺便说一句,有同步运行的计时器,所以不要将“计时器”的概念与“线程”混为一谈)或直接绑定(bind)到实体集合上的“集合已更改”事件。当检测到更改时,您只需在模型中执行该更改所需的任何业务逻辑(例如应用转换、排序、日志记录等),然后通知 View 模型已发生更改。

关于c# - 如何在数据库更改时更新 WPF UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39875636/

相关文章:

c# - WPF : Re-usable template for image buttons?

c# - WPF 应用程序在未右键单击并选择 "Run as administrator"的情况下运行时出现性能问题

java - REST with JAX-RS - 处理长时间运行的操作

c# - double.parse 将两位零小数转换为一位小数

c# - 在 WPF 中,如何在控件模板中获取命令以绑定(bind)到父项中的属性?

c# - Silverlight 4 剪贴板安全异常 "access is not allowed"?

java - 当独立程序想要退出时,@Scheduled Tasks 使 JVM 保持挂起状态,需要杀死 JVM

java - 为什么同步的 getter 像 volatile read 一样工作?

c# - 集合被修改;枚举操作可能无法执行

c# - CRM 2011,解决方案和发布者选项不可用