using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows.Data; using System.Windows.Input; namespace XLAB2 { internal sealed class AccountingBookDirectoryWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; private readonly DocumentNumberDirectoryService _service; private string _searchText; private GroupOption _selectedItem; private string _statusText; public AccountingBookDirectoryWindowViewModel(DocumentNumberDirectoryService service, IDialogService dialogService) { _service = service ?? throw new ArgumentNullException("service"); _dialogService = dialogService ?? throw new ArgumentNullException("dialogService"); Items = new ObservableCollection(); ItemsView = CollectionViewSource.GetDefaultView(Items); ItemsView.Filter = FilterItems; AddCommand = new RelayCommand(delegate { AddItem(); }); DeleteCommand = new RelayCommand(delegate { DeleteSelectedItem(); }, delegate { return SelectedItem != null; }); EditCommand = new RelayCommand(delegate { EditSelectedItem(); }, delegate { return SelectedItem != null; }); RefreshCommand = new RelayCommand(delegate { RefreshItems(null); }); 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 ICommand RefreshCommand { get; private set; } public string SearchText { get { return _searchText; } set { if (SetProperty(ref _searchText, value)) { ItemsView.Refresh(); UpdateStatus(); } } } public GroupOption SelectedItem { get { return _selectedItem; } set { if (SetProperty(ref _selectedItem, value)) { RaiseCommandStates(); } } } public string StatusText { get { return _statusText; } private set { SetProperty(ref _statusText, value); } } public void Initialize() { RunOperation(delegate { RefreshItems(null); }, false); } private void AddItem() { var result = _dialogService.ShowAccountingBookEditDialog(new GroupOption(), true, Items.ToList()); if (result == null) { return; } RunOperation(delegate { var items = CloneItems(Items); items.Add(CloneItem(result)); _service.SaveAccountingBooks(items); RefreshItems(result.Key); _dialogService.ShowInfo("Запись справочника добавлена."); }, true); } private bool Contains(string source, string searchText) { return !string.IsNullOrWhiteSpace(source) && source.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0; } private void DeleteSelectedItem() { if (SelectedItem == null) { return; } var selectedItem = SelectedItem; if (!_dialogService.Confirm(string.Format("Удалить книгу учета \"{0}\"?", selectedItem.Title))) { return; } RunOperation(delegate { var items = CloneItems(Items); items.RemoveAll(delegate(GroupOption item) { return string.Equals(item.Key, selectedItem.Key, StringComparison.OrdinalIgnoreCase); }); _service.SaveAccountingBooks(items); RefreshItems(null); _dialogService.ShowInfo("Запись справочника удалена."); }, true); } private void EditSelectedItem() { if (SelectedItem == null) { return; } var seed = CloneItem(SelectedItem); var result = _dialogService.ShowAccountingBookEditDialog(seed, false, Items.ToList()); if (result == null) { return; } RunOperation(delegate { var items = CloneItems(Items); var index = items.FindIndex(delegate(GroupOption item) { return string.Equals(item.Key, seed.Key, StringComparison.OrdinalIgnoreCase); }); if (index < 0) { throw new InvalidOperationException("Не удалось найти книгу учета для обновления."); } items[index] = CloneItem(result); _service.SaveAccountingBooks(items); RefreshItems(result.Key); _dialogService.ShowInfo("Запись справочника обновлена."); }, true); } private bool FilterItems(object item) { var directoryItem = item as GroupOption; if (directoryItem == null) { return false; } if (string.IsNullOrWhiteSpace(SearchText)) { return true; } return Contains(directoryItem.Key, SearchText) || Contains(directoryItem.Title, SearchText); } private void RaiseCommandStates() { ((RelayCommand)AddCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeleteCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditCommand).RaiseCanExecuteChanged(); ((RelayCommand)RefreshCommand).RaiseCanExecuteChanged(); } private void RefreshItems(string keyToSelect) { var items = _service.LoadAccountingBooks(); var currentKey = string.IsNullOrWhiteSpace(keyToSelect) ? (SelectedItem == null ? null : SelectedItem.Key) : keyToSelect; Items.Clear(); foreach (var item in items) { Items.Add(CloneItem(item)); } ItemsView.Refresh(); SelectedItem = string.IsNullOrWhiteSpace(currentKey) ? Items.FirstOrDefault() : Items.FirstOrDefault(delegate(GroupOption item) { return string.Equals(item.Key, currentKey, StringComparison.OrdinalIgnoreCase); }) ?? Items.FirstOrDefault(); UpdateStatus(); } private void RunOperation(Action action, bool showWarningForInvalidOperation) { try { action(); } catch (InvalidOperationException ex) { if (showWarningForInvalidOperation) { _dialogService.ShowWarning(ex.Message); return; } _dialogService.ShowError(ex.Message); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } } private static GroupOption CloneItem(GroupOption item) { return new GroupOption { Key = item == null ? string.Empty : item.Key, Title = item == null ? string.Empty : item.Title }; } private static List CloneItems(IEnumerable items) { var result = new List(); foreach (var item in items ?? Array.Empty()) { result.Add(CloneItem(item)); } return result; } private void UpdateStatus() { var visibleCount = ItemsView.Cast().Count(); StatusText = string.Format("Всего записей: {0}. По фильтру: {1}.", Items.Count, visibleCount); } } }