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 SpnmtpDirectoryWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; private readonly PsvDataService _service; private bool _isBusy; private string _searchText; private SpnmtpDirectoryItem _selectedItem; private string _statusText; public SpnmtpDirectoryWindowViewModel(PsvDataService service, IDialogService dialogService) { _service = service; _dialogService = dialogService; Items = new ObservableCollection(); 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 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 SpnmtpDirectoryItem 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.ShowSpnmtpEditDialog(new SpnmtpDirectoryItem(), true, Items.ToList()); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddSpnmtpItem(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.DeleteSpnmtpItem(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 SpnmtpDirectoryItem { Id = SelectedItem.Id, Name = SelectedItem.Name, SpecialName = SelectedItem.SpecialName }; var result = _dialogService.ShowSpnmtpEditDialog(seed, false, Items.ToList()); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdateSpnmtpItem(result); }); await RefreshCoreAsync(result.Id); _dialogService.ShowInfo("Запись справочника обновлена."); }); } private async Task ExecuteBusyOperationAsync(Func operation) { try { IsBusy = true; await operation(); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } finally { IsBusy = false; } } private async Task ExecuteMutationOperationAsync(Func 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 SpnmtpDirectoryItem; if (directoryItem == null) { return false; } if (string.IsNullOrWhiteSpace(SearchText)) { return true; } return Contains(directoryItem.Name, SearchText) || Contains(directoryItem.SpecialName, SearchText) || directoryItem.Id.ToString().IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; } private async Task RefreshCoreAsync(int? idToSelect) { var items = await _service.LoadSpnmtpItemsAsync(); 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(SpnmtpDirectoryItem 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 operation) { try { await ExecuteBusyOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private async void RunMutationOperation(Func operation) { try { await ExecuteMutationOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private void UpdateStatus() { var visibleCount = ItemsView.Cast().Count(); StatusText = string.Format("Всего записей: {0}. По фильтру: {1}.", Items.Count, visibleCount); } } }