Files
XLAB/XLAB2/SpoiDirectoryWindowViewModel.cs
Курнат Андрей a47a7a5a3b edit
2026-03-19 23:31:41 +03:00

295 lines
8.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
namespace XLAB2
{
internal sealed class SpoiDirectoryWindowViewModel : ObservableObject
{
private readonly IDialogService _dialogService;
private readonly PsvDataService _service;
private bool _isBusy;
private string _searchText;
private SpoiDirectoryItem _selectedItem;
private string _statusText;
public SpoiDirectoryWindowViewModel(PsvDataService service, IDialogService dialogService)
{
_service = service;
_dialogService = dialogService;
Items = new ObservableCollection<SpoiDirectoryItem>();
ItemsView = CollectionViewSource.GetDefaultView(Items);
ItemsView.Filter = FilterItems;
AddCommand = new RelayCommand(delegate { AddItemAsync(); }, delegate { return !IsBusy; });
DeleteCommand = new RelayCommand(delegate { DeleteSelectedItemAsync(); }, delegate { return !IsBusy && SelectedItem != null; });
EditCommand = new RelayCommand(delegate { EditSelectedItemAsync(); }, delegate { return !IsBusy && SelectedItem != null; });
RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; });
UpdateStatus();
}
public ICommand AddCommand { get; private set; }
public ICommand DeleteCommand { get; private set; }
public ICommand EditCommand { get; private set; }
public ObservableCollection<SpoiDirectoryItem> Items { get; private set; }
public ICollectionView ItemsView { get; private set; }
public bool IsBusy
{
get { return _isBusy; }
private set
{
if (SetProperty(ref _isBusy, value))
{
RaiseCommandStates();
}
}
}
public ICommand RefreshCommand { get; private set; }
public string SearchText
{
get { return _searchText; }
set
{
if (SetProperty(ref _searchText, value))
{
ItemsView.Refresh();
UpdateStatus();
}
}
}
public SpoiDirectoryItem SelectedItem
{
get { return _selectedItem; }
set
{
if (SetProperty(ref _selectedItem, value))
{
RaiseCommandStates();
}
}
}
public string StatusText
{
get { return _statusText; }
private set { SetProperty(ref _statusText, value); }
}
public async Task InitializeAsync()
{
await ExecuteBusyOperationAsync(delegate { return RefreshCoreAsync(null); });
}
private void AddItemAsync()
{
var result = _dialogService.ShowSpoiEditDialog(new SpoiDirectoryItem(), true, Items.ToList());
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
var createdId = await Task.Run(delegate { return _service.AddSpoiItem(result); });
await RefreshCoreAsync(createdId);
_dialogService.ShowInfo("Запись справочника добавлена.");
});
}
private bool Contains(string source, string searchText)
{
return !string.IsNullOrWhiteSpace(source)
&& source.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0;
}
private void DeleteSelectedItemAsync()
{
if (SelectedItem == null)
{
return;
}
var selectedItem = SelectedItem;
if (!_dialogService.Confirm(string.Format("Удалить запись \"{0}\"?", selectedItem.Name)))
{
return;
}
RunMutationOperation(async delegate
{
var deleteResult = await Task.Run(delegate { return _service.DeleteSpoiItem(selectedItem.Id); });
if (!deleteResult.IsDeleted)
{
_dialogService.ShowWarning(deleteResult.WarningMessage);
return;
}
await RefreshCoreAsync(null);
_dialogService.ShowInfo("Запись справочника удалена.");
});
}
private void EditSelectedItemAsync()
{
if (SelectedItem == null)
{
return;
}
var seed = new SpoiDirectoryItem
{
Id = SelectedItem.Id,
Code = SelectedItem.Code,
Name = SelectedItem.Name
};
var result = _dialogService.ShowSpoiEditDialog(seed, false, Items.ToList());
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
await Task.Run(delegate { _service.UpdateSpoiItem(result); });
await RefreshCoreAsync(result.Id);
_dialogService.ShowInfo("Запись справочника обновлена.");
});
}
private async Task ExecuteBusyOperationAsync(Func<Task> operation)
{
try
{
IsBusy = true;
await operation();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
finally
{
IsBusy = false;
}
}
private async Task ExecuteMutationOperationAsync(Func<Task> operation)
{
try
{
IsBusy = true;
await operation();
}
catch (InvalidOperationException ex)
{
_dialogService.ShowWarning(ex.Message);
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
finally
{
IsBusy = false;
}
}
private bool FilterItems(object item)
{
var directoryItem = item as SpoiDirectoryItem;
if (directoryItem == null)
{
return false;
}
if (string.IsNullOrWhiteSpace(SearchText))
{
return true;
}
return Contains(directoryItem.Code, SearchText)
|| Contains(directoryItem.Name, SearchText)
|| directoryItem.Id.ToString().IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0;
}
private async Task RefreshCoreAsync(int? idToSelect)
{
var items = await _service.LoadSpoiItemsAsync();
var currentId = idToSelect ?? (SelectedItem == null ? (int?)null : SelectedItem.Id);
Items.Clear();
foreach (var item in items)
{
Items.Add(item);
}
ItemsView.Refresh();
SelectedItem = currentId.HasValue
? Items.FirstOrDefault(delegate(SpoiDirectoryItem item) { return item.Id == currentId.Value; })
: Items.FirstOrDefault();
UpdateStatus();
}
private void RefreshAsync()
{
RunBusyOperation(delegate { return RefreshCoreAsync(null); });
}
private void RaiseCommandStates()
{
((RelayCommand)AddCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteCommand).RaiseCanExecuteChanged();
((RelayCommand)EditCommand).RaiseCanExecuteChanged();
((RelayCommand)RefreshCommand).RaiseCanExecuteChanged();
}
private async void RunBusyOperation(Func<Task> operation)
{
try
{
await ExecuteBusyOperationAsync(operation);
}
catch (Exception ex)
{
IsBusy = false;
_dialogService.ShowError(ex.Message);
}
}
private async void RunMutationOperation(Func<Task> operation)
{
try
{
await ExecuteMutationOperationAsync(operation);
}
catch (Exception ex)
{
IsBusy = false;
_dialogService.ShowError(ex.Message);
}
}
private void UpdateStatus()
{
var visibleCount = ItemsView.Cast<object>().Count();
StatusText = string.Format("Всего записей: {0}. По фильтру: {1}.", Items.Count, visibleCount);
}
}
}