简体   繁体   English

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

[英]How to update WPF UI as database changes

I am writing an application in C#/WPF/Entity Framework DB first that communicates with a proprietary piece of industrial hardware that measures values like flow and temperature from a coolant line. 我首先在C#/ WPF / Entity Framework DB中编写一个应用程序,该应用程序与专有的工业硬件进行通信,该工业硬件可测量诸如冷却液管线中的流量和温度之类的值。 Those values frequently are updated in my SQL Server database with a thread that runs in the background, and then are displayed in my UI. 这些值经常使用在后台运行的线程在SQL Server数据库中进行更新,然后显示在UI中。

My concern currently is with how I update my UI to reflect those changes. 目前,我最关心的是如何更新UI以反映这些更改。 Here's an example of how I update a datagrid: 这是我如何更新数据网格的示例:

I set my datacontext to my viewmodel, and instantiate a thread that runs every second: 我将我的数据上下文设置为我的视图模型,并实例化一个每秒运行的线程:

    _DataContext = new ViewModels.SummaryTable_ViewModel();
    this.DataContext = _DataContext;
    UIUpdateThread = new Thread(UIUpdaterThread);
    UIUpdateThread.IsBackground = true;
    UIUpdateThread.Start();       

The model my grid is based on is an IList<> that looks like this: 我的网格所基于的模型是一个IList <>,看起来像这样:

    private IList<channel> _channel;
    public IList<channel> Channels
    {
        get
        {
            return _channel;
        }
        set
        {
            _channel = value;
            //NotifyPropertyChanged();
            OnPropertyChanged("Channels");
        }
    }

Then every second my UIUpdateThread calls my FillChannels() method which is as follows, then the grid updates based on the propertychanged notification: 然后,我的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;
                }
            }

So my question is this: is there a better, more elegant way to do this? 所以我的问题是:有没有更好,更优雅的方法呢? This feels "wrong" for lack of a better term. 由于缺少更好的用语,这感觉是“错误的”。 And it has bad side effects, like resetting the user-set sort on my datagrid every time the thread runs. 而且它具有不良的副作用,例如每次线程运行时都会在我的数据网格上重置用户设置的排序。 Also I think it breaks the MVVM pattern, though I'm not certain. 我也认为它打破了MVVM模式,尽管我不确定。

For example I'm thinking what if the thread that talks to my hardware updates a shared Channel object every time it polls the hardware for data, and I just bind my UIs to it, that way I wouldn't have to run this thread (or the other threads on my other UIs that do the same thing), just update based on PropertyChanged notifications. 例如,我在考虑与硬件对话的线程在每次轮询硬件以获取数据时更新一个共享的Channel对象,而我只需将UI绑定到该对象,这样我就不必运行此线程(或其他UI上执行相同操作的其他线程),仅根据PropertyChanged通知进行更新。 Or is there some other method I'm unaware of completely? 还是我完全不了解其他方法? When searching for an answer I saw mentions of the unit of work pattern, with which I'm unfamiliar, is that a relevant concept here? 在寻找答案时,我看到了我不熟悉的工作单元模式的提法,这是一个相关的概念吗?

As you can see, I'm not too sure where to go from here, and could really use some help. 如您所见,我不太确定从这里出发,可以真正使用一些帮助。 Sorry for the wall of text, I just wanted to be as thorough as possible. 对不起,我只想尽可能地透彻。 Any assistance would be greatly appreciated. 任何帮助将不胜感激。 Thanks. 谢谢。

I think your model should be the one that's notifying your view model when there is new data. 我认为您的模型应该是在有新数据时通知您的视图模型的模型。 You should put whatever mechanism that accomplishes this (like the timer I assume you're using) into the model. 您应该将完成此任务的任何机制(例如我假设您正在使用的计时器)放入模型中。

Basically, your model notifies your view model, and your view model notifies the view that there are data changes. 基本上,您的模型会通知您的视图模型,而您的视图模型会通知视图有数据更改。 If you setup your view correctly -- and use XAML rather than code-behinds, it should all come together automatically via the data bindings between the view and the view model. 如果您正确设置了视图-并使用XAML而不是使用代码隐藏,则所有视图都应通过视图和视图模型之间的数据绑定自动组合在一起。

Regarding sorting: that should be a separate property of your view model that's bound to the sorting property on your view's grid. 关于排序:应该是视图模型的一个单独属性,该属性绑定到视图网格上的sorting属性。 Your model should maintain the user-set sort, and apply it appropriately to the updated data before it notifies the view model when data is changed. 您的模型应保持用户设置的排序,并将其适当地应用于更新后的数据,然后在数据更改时通知视图模型。

I'm not sure if unit of work is applicable here since you're not talking about persisting related rows of data to multiple tables and doing so as one transaction -- you're only reading data. 我不确定工作单​​元是否适用于这里,因为您不是在谈论将相关的数据行持久保存到多个表中,而是作为一个事务进行操作-您只在读取数据。 I could be wrong though, as I haven't studied unit of work that much. 不过,我可能错了,因为我没有研究太多的工作单元。


To address your questions in the comments: 要在评论中解决您的问题:

Let's take a step back. 让我们退后一步。 Your view model should only be concerned with logic that's related to the presentation of the associated view. 您的视图模型应该关注与关联视图的表示有关的逻辑。 It should not have any data access code or code that performs any business logic or domain-related tasks; 它不应具有任何数据访问代码或执行任何业务逻辑或与域相关的任务的代码; that code goes in what is collectively called the "model" (forgive me if you already have this, but it's hard to tell exactly where the code you provided in your question resides). 该代码将被统称为“模型”(请原谅我,如果您已经拥有此模型,但是很难确切说明问题中提供的代码在哪里)。

The model can consist of a number of classes that perform different business logic tasks or that represent your domain/entity POCOs (like your entity framework generated classes). 该模型可以由执行不同业务逻辑任务或代表您的域/实体POCO的许多类组成(例如您的实体框架生成的类)。

I'm a little unclear what your Channel object is and how it's separate from your entity class/POCO, ie the EF-generated model. 我还不清楚您的Channel对象是什么,以及它与实体类/ POCO(即由EF生成的模型)如何分离。 But again, your interaction with EF and the maintenance and logic related to your entities should happen in the Model. 但同样,您与EF的交互以及与实体相关的维护和逻辑应在模型中进行。

So yes, the idea would be that you look for data changes in the model using whatever mechanism you want to -- eg a timer (btw there are timers that run synchronously, so don't conflate the notion of "timer" with "thread") or binding directly to the "collection changed" event on your collection of entities. 因此,是的,您的想法将是使用所需的任何机制来寻找模型中的数据更改-例如,计时器(顺便说一下,有一些计时器是同步运行的,因此请不要将“计时器”的概念与“线程”混为一谈。 ”)或直接绑定到您的实体集合上的“集合更改”事件。 When a change is detected, you would simply do whatever business logic is required for that change in the model (like applying transformations, sorting, logging, etc.) and then notify the view model that the change has occurred. 当检测到更改时,您只需执行模型中更改所需的任何业务逻辑(例如应用转换,排序,日志记录等),然后通知视图模型已发生更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM