如何使不同屏幕上显示的同一来源的数据保持同步

本文关键字:数据 同步 屏幕 显示 何使不 | 更新日期: 2023-09-27 18:29:38

我有一个场景,其中至少有两个屏幕将同时显示,它们具有相同的源。在一个屏幕上,该数据是只读的,在另一个屏幕是可编辑的。我需要同步两个屏幕上的数据。此外,不同的用户可以修改数据。

假设这是一系列行动:

  1. 用户打开一个包含集合a中只读数据的屏幕a
  2. 用户需要向集合A添加新项目,因此屏幕B打开
  3. 用户在屏幕B上添加了3个新项目,然后将其关闭
  4. 屏幕上的集合A需要包含新项目

可能存在两个以上屏幕包含来自同一来源(收集类型)的数据的情况。

我使用MVVM灯光和ViewModelLocator模式来向视图公开ViewModels。目前我在ViewModel的构造函数中获取数据。这意味着,如果我缓存ViewMOdel实例以供重用,我将只获取一次数据,所有屏幕都将使用相同的集合作为源,因此同步是自动完成的。这也意味着,如果网络上的其他用户更改数据,新数据将永远不可见,因为数据只提取一次(在ViewModel创建期间)。

另一种方法是,ViewModelLocator每次被请求时都会返回ViewModel的新实例。这意味着总是从数据库中提取新的数据,所以其他网络用户更改数据的问题不再存在。但是,在这种情况下,每个ViewModel将包含不同的集合数据实例,因此只有数据的编辑会自动同步,添加/删除实体不会自动同步。

那么,在请求ViewModel时获取新数据,并在不同屏幕之间同步数据的最佳方式是什么?

如何使不同屏幕上显示的同一来源的数据保持同步

我在评论中解释得很差,所以我创建了一个我所说的例子。它使用CM,但这个想法可以转移到MVVM光。

我创建了两个视图模型:SharingScreen1ViewModelSharingScreen2ViewModel,以及两个视图:SharingScreen1ViewSharingScreen2View

每个VM都会注入SharedViewModel单例。从左侧导航,您可以在2个视图之间切换。SharedDataViewModel属性最初是在SharingScreen1ViewModel中的OnInitialize方法中设置的。然后,可以通过单击按钮在SharingScreen2ViewModel中更改这些值。切换回View one,其值也发生了更改。

当我提到DispatcherTimer时,我指的是一项要求,我必须每30秒刷新一点数据。计时器是更新这些数据的多种方法之一。正如您在本例中看到的,当初始化第一个ViewModel时,数据被设置一次,当用户单击按钮时,数据在另一个ViewModel中被再次设置。

接口SharedViewModel实现:

 public interface ISharedViewModel
    {
        string FirstName { get; set; }
        string LastName { get; set; }
        string Address { get; set; }
    }

SharingScreen1ViewModel:

 [Export(typeof (SharingScreen1ViewModel))]
    public class SharingScreen1ViewModel : Screen
    {
        [ImportingConstructor]
        public SharingScreen1ViewModel(ISharedViewModel sharedViewModel)
        {
            DisplayName = "Shared Data Screen 1";
            SharedViewModel = sharedViewModel;
        }
        public ISharedViewModel SharedViewModel { get; set; }
        protected override void OnInitialize()
        {
            base.OnInitialize();
            SharedViewModel.FirstName = "Jimmy";
            SharedViewModel.LastName = "Hugh";
            SharedViewModel.Address = "555 South St.";
        }
    }

SharingScreen2ViewModel:

[Export(typeof (SharingScreen2ViewModel))]
    public class SharingScreen2ViewModel : Screen
    {
        [ImportingConstructor]
        public SharingScreen2ViewModel(ISharedViewModel sharedViewModel)
        {
            DisplayName = "Shared Data Screen 2";
            SharedViewModel = sharedViewModel;
        }
        public ISharedViewModel SharedViewModel { get; set; }
        public void ChangeSharedData()
        {
            SharedViewModel.FirstName = "New First Name";
            SharedViewModel.LastName = "New Last Name:";
            SharedViewModel.Address = "New Address";
        }
    }

由于您使用的是MVVM Light的ViewModelLocator,您可能有类似的代码

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        // register your types with your favourite DI container
    }
    public MainViewModel Main
    {
        get 
        { 
            var vm = // resolve singleton instance, data obtained in constructor
            return vm;
        }
    }

像这样简单的更改是否足以满足您的要求?

public class ViewModelLocator
{
    ...
    public MainViewModel Main
    {
        get 
        { 
            var vm = // resolve singleton instance
            vm.RefreshData(); // data obtained/updated here
            return vm;
        }
    }