I have a scenario where at least 2 screens will be displayed at the same time that have the same source. On one screen this data is read-only, on other is editable. I need data on both screens to be synchronized. Also, data can be modified by different users.
Lets say that this is the sequence of actions:
There could be cases where more than 2 screens contain data from the same source (collection type).
I am using MVVM light and ViewModelLocator pattern to expose ViewModels to Views. Currently I fetch data in ViewModel's constructor. This means that if I cache ViewMOdel instance for reuse, I will fetch the data only once, all screens will use the same collection as source, so sync is done automatically. This also means that if other user on network changes data, new data will never be visible, since data is fetched only once (during ViewModel creation).
Another approach would be that ViewModelLocator returns new instance of ViewModel each time it is requested. This means that fresh data from database is always fetched, so issue with other network users changing data no longer exists. However, in this case each ViewModel will contain different instance of collection data, so only editing of data is being automatically synchronized, adding/deleting an entity is not being synchronized automatically.
So, what is the best way to have fresh data acquired when a ViewModel is requested, and also having data being synchronized between different screens?
I did a poor job of explaining this in my comments so I created an example of what I was talking about. It's using CM but the idea can be transferred to MVVM-light.
I created 2 view models: SharingScreen1ViewModel
and SharingScreen2ViewModel
and 2 Views: SharingScreen1View
and SharingScreen2View
.
Each VM gets the SharedViewModel singleton injected. From the left nav you can toggle between the 2 Views. The SharedDataViewModel
properties are initially set in the OnInitialize method that lives in SharingScreen1ViewModel
. Then the values can be changed in SharingScreen2ViewModel by clicking the button. Toggle back to View one and the values have changed for it as well.
When I mentioned the DispatcherTimer, I was referring to a requirement I had to refresh a bit of data every 30 seconds. The timer was one of many ways to update this data. As you can see in this example the data is being set one time when the first ViewModel is initialized and the data is being set again in another ViewModel when the user clicks a button.
Interface SharedViewModel
implements:
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";
}
}