如何在 Maui 应用程序中重用全局已加载的可观察集合?

问题描述 投票:0回答:1

我有一个毛伊岛应用程序,其中在不同视图上跨应用程序使用 4-5 个可观察集合。目前我有一个服务,它通过存储库从数据库加载并触发一个事件来更新可观察的集合,但这需要在使用此数据的每个页面上加载。

待办服务

public class ToDoService
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly List<ToDo> _toDos;
    public IEnumerable<ToDo> ToDos => _toDos;

    public event Action ToDosLoaded;
    public event Action<ToDo> ToDoAdded;
    public event Action<ToDo> ToDoUpdated;
    public event Action<Guid> ToDoDeleted;

    public ToDoService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _toDos = new List<ToDo>();
    }

    public async Task Load()
    {
        IEnumerable<ToDo> toDos = await _unitOfWork.ToDo.GetAllAsync();
        _toDos.Clear();
        _toDos.AddRange(toDos);

        ToDosLoaded?.Invoke();
    }

    public async Task Add(ToDo toDo, bool isCopy = false)
    {
        var saved = await _unitOfWork.ToDo.SaveAsync(toDo);

        if (saved is not null)
        {
            _toDos.Add(toDo);

            ToDoAdded?.Invoke(toDo);
        }
    }

    public async Task Update(ToDo toDo)
    {
        var saved = await _unitOfWork.ToDo.SaveAsync(toDo);

        if (saved is not null)
        {
            int currentIndex = _toDos.FindIndex(y => y.LocalId == saved.LocalId);

            if (currentIndex != -1)
            {
                _toDos[currentIndex] = saved;
            }
            else
            {
                _toDos.Add(saved);
            }

            ToDoUpdated?.Invoke(saved);
        }
    }

    public async Task Delete(ToDo toDo)
    {
        var deleted = await _unitOfWork.ToDO.DeleteAsync(toDo.LocalId);

        if (deleted)
        {
            _toDos.RemoveAll(g => g.LocalId == toDo.LocalId);

            ToDoDeleted?.Invoke(toDo.LocalId);
        }
    }
}

ToDoListingViewModel

private readonly ToDoService _toDoStoreService;

[ObservableProperty]
private ObservableCollection<ToDoListingPreviewItemViewModel> _toDoListingPreviewItemViewModels;

public ToDoListingViewModel(ToDoService toDoStoreService)
{
    ToDoListingPreviewItemViewModels = [];

    _toDoStoreService = toDoStoreService;
    _toDoStoreService.ToDosLoaded += ToDoStoreService_ToDosLoaded;
    _toDoStoreService.ToDoAdded += ToDoStoreService_ToDoAdded;
    _toDoStoreService.ToDoUpdated += ToDoStoreService_ToDoUpdated;
    _toDoStoreService.ToDoDeleted += ToDoStoreService_ToDoDeleted;

    ToDoListingPreviewItemViewModels.CollectionChanged += ToDoListingItemViewModels_CollectionChanged;
}

private void ToDoStoreService_ToDosLoaded()
{
    ToDoListingPreviewItemViewModels.Clear();

    foreach (ToDo toDo in _toDoStoreService.ToDos)
    {
        AddToDo(toDo);
    }
}

private void ToDoStoreService_ToDoAdded(ToDo toDo)
{
    AddToDo(toDo);
}

private void ToDoStoreService_ToDoUpdated(ToDo toDo)
{
    ToDoListingPreviewItemViewModel toDoListingPreviewItemViewModel =
            ToDoListingPreviewItemViewModels.FirstOrDefault(t => t.ToDo.LocalId == toDo.LocalId);

    if (toDoListingPreviewItemViewModel != null)
    {
        toDoListingPreviewItemViewModel.Update(toDo);
    }
}

private void ToDoStoreService_ToDoDeleted(Guid id)
{
    ToDoListingPreviewItemViewModel toDoListingPreviewItemViewModel = ToDoListingPreviewItemViewModels.FirstOrDefault(y => y.ToDo?.LocalId == id);

    if (toDoListingPreviewItemViewModel != null)
    {
        ToDoListingPreviewItemViewModels.Remove(toDoListingPreviewItemViewModel);
    }
}

private void ToDoListingItemViewModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    OnPropertyChanged(nameof(Name));
}

private void AddToDo(ToDo toDo)
{
    ToDoListingPreviewItemViewModel toDoListingPreviewItemViewModel = new(toDo);
    ToDoListingPreviewItemViewModels.Add(toDoListingPreviewItemViewModel);
}

public void Dispose()
{
    _toDoStoreService.ToDosLoaded -= ToDoStoreService_ToDosLoaded;
    _toDoStoreService.ToDoAdded -= ToDoStoreService_ToDoAdded;
    _toDoStoreService.ToDoUpdated -= ToDoStoreService_ToDoUpdated;
    _toDoStoreService.ToDoDeleted -= ToDoStoreService_ToDoDeleted;

    ToDoListingPreviewItemViewModels.CollectionChanged -= ToDoListingItemViewModels_CollectionChanged;
}

通过这种方式我可以简单地创建

public ToDosListingViewModel ToDos { get; }
ToDos = new ToDosListingViewModel (_todosStoreService);
// and load data
await _todosStoreService.Load();

通过此设置,如果任何页面需要使用此集合,我需要首先加载所有内容,如果发生任何更改,它将触发之前已加载的所有列表,以更新整个应用程序中的所有列表。这很棒,但我想避免多次加载并订阅要更新的事件。如何在整个应用程序中使用一个列表属性?

我是否应该将 ToDosListingViewModel 和 ToDoService 单例化,当应用程序启动时,我只需加载所有数据一次,仅此而已? 我应该在 App.cs 中添加一个全局列表变量吗?

mvvm maui observablecollection
1个回答
0
投票

为此,您可以为您的应用程序创建一个静态全局类。您可以在您的应用程序中访问和更新这些参数。

例如,我们可以先定义一个全局类(AppData.cs)并添加一个变量

Items_test
:

public static class AppData
{
    public static ObservableCollection<string> Items_test { get; set; } = new ObservableCollection<string>() {"test1", "test2" };

}

然后我们可以在应用程序的任何页面上访问

ObservableCollection<>
类型的变量。

例如:

 AppData.Items_test.Add("test3");
© www.soinside.com 2019 - 2024. All rights reserved.