295 lines
8.9 KiB
C#
295 lines
8.9 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|