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

477 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
namespace XLAB2
{
internal sealed class FrpdDirectoryWindowViewModel : ObservableObject
{
private readonly IFrpdDirectoryDialogService _dialogService;
private readonly FrpdDirectoryService _service;
private List<FrpdDirectoryItem> _frpdCache;
private bool _isBusy;
private string _searchText;
private FrpdDirectoryItem _selectedFrpd;
private FrpdvdDirectoryItem _selectedFrpdvd;
private string _statusText;
public FrpdDirectoryWindowViewModel(FrpdDirectoryService service, IFrpdDirectoryDialogService dialogService)
{
_service = service;
_dialogService = dialogService;
_frpdCache = new List<FrpdDirectoryItem>();
FrpdItems = new ObservableCollection<FrpdDirectoryItem>();
FrpdvdItems = new ObservableCollection<FrpdvdDirectoryItem>();
AddFrpdCommand = new RelayCommand(delegate { AddFrpdAsync(); }, delegate { return !IsBusy; });
EditFrpdCommand = new RelayCommand(delegate { EditFrpdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; });
DeleteFrpdCommand = new RelayCommand(delegate { DeleteFrpdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; });
AddFrpdvdCommand = new RelayCommand(delegate { AddFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpd != null; });
EditFrpdvdCommand = new RelayCommand(delegate { EditFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpdvd != null; });
DeleteFrpdvdCommand = new RelayCommand(delegate { DeleteFrpdvdAsync(); }, delegate { return !IsBusy && SelectedFrpdvd != null; });
RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; });
UpdateStatus();
}
public ICommand AddFrpdCommand { get; private set; }
public ICommand AddFrpdvdCommand { get; private set; }
public ICommand DeleteFrpdCommand { get; private set; }
public ICommand DeleteFrpdvdCommand { get; private set; }
public ICommand EditFrpdCommand { get; private set; }
public ICommand EditFrpdvdCommand { get; private set; }
public ObservableCollection<FrpdDirectoryItem> FrpdItems { get; private set; }
public ObservableCollection<FrpdvdDirectoryItem> FrpdvdItems { get; private set; }
public ICommand RefreshCommand { get; private set; }
public bool IsBusy
{
get { return _isBusy; }
private set
{
if (SetProperty(ref _isBusy, value))
{
RaiseCommandStates();
}
}
}
public string SearchText
{
get { return _searchText; }
set
{
if (SetProperty(ref _searchText, value))
{
ApplySearchFilter();
UpdateStatus();
}
}
}
public FrpdDirectoryItem SelectedFrpd
{
get { return _selectedFrpd; }
set
{
if (SetProperty(ref _selectedFrpd, value))
{
RaiseCommandStates();
LoadFrpdvdForSelection();
UpdateStatus();
}
}
}
public FrpdvdDirectoryItem SelectedFrpdvd
{
get { return _selectedFrpdvd; }
set
{
if (SetProperty(ref _selectedFrpdvd, value))
{
RaiseCommandStates();
UpdateStatus();
}
}
}
public string StatusText
{
get { return _statusText; }
private set { SetProperty(ref _statusText, value); }
}
public async Task InitializeAsync()
{
await ExecuteBusyOperationAsync(async delegate { await RefreshFrpdCoreAsync(null, null); });
}
private void AddFrpdAsync()
{
var result = _dialogService.ShowFrpdEditDialog(new FrpdDirectoryItem(), true, _frpdCache.ToList(), _service);
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
var createdId = await Task.Run(delegate { return _service.AddFrpdItem(result); });
await RefreshFrpdCoreAsync(createdId, null);
_dialogService.ShowInfo("Запись FRPD добавлена.");
});
}
private void AddFrpdvdAsync()
{
if (SelectedFrpd == null)
{
return;
}
var result = _dialogService.ShowFrpdvdEditDialog(new FrpdvdDirectoryItem { FrpdId = SelectedFrpd.Id }, true, FrpdvdItems.ToList(), _service);
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
var createdId = await Task.Run(delegate { return _service.AddFrpdvdItem(result); });
await RefreshFrpdCoreAsync(result.FrpdId, createdId);
_dialogService.ShowInfo("Запись FRPDVD добавлена.");
});
}
private void ApplyFrpdFilter(int? preferredId)
{
var filteredItems = _frpdCache.Where(delegate(FrpdDirectoryItem item) { return MatchesSearch(item); }).ToList();
FrpdItems.Clear();
foreach (var item in filteredItems)
{
FrpdItems.Add(item);
}
SelectedFrpd = preferredId.HasValue
? FrpdItems.FirstOrDefault(delegate(FrpdDirectoryItem item) { return item.Id == preferredId.Value; })
: FrpdItems.FirstOrDefault();
}
private void ApplySearchFilter()
{
if (!IsBusy)
{
ApplyFrpdFilter(SelectedFrpd == null ? (int?)null : SelectedFrpd.Id);
}
}
private static FrpdDirectoryItem CloneFrpd(FrpdDirectoryItem source)
{
return new FrpdDirectoryItem
{
CreatedOn = source.CreatedOn,
Guid = source.Guid,
Id = source.Id,
LiquidatedOn = source.LiquidatedOn,
LocalCode = source.LocalCode,
Name = source.Name,
ParentId = source.ParentId,
ParentName = source.ParentName
};
}
private static FrpdvdDirectoryItem CloneFrpdvd(FrpdvdDirectoryItem source)
{
return new FrpdvdDirectoryItem
{
ActivityId = source.ActivityId,
ActivityName = source.ActivityName,
FrpdId = source.FrpdId,
Id = source.Id
};
}
private void DeleteFrpdAsync()
{
if (SelectedFrpd == null)
{
return;
}
var selected = SelectedFrpd;
if (!_dialogService.Confirm(string.Format("Удалить организацию/подразделение \"{0}\"?", selected.Name)))
{
return;
}
RunMutationOperation(async delegate
{
var result = await Task.Run(delegate { return _service.DeleteFrpdItem(selected.Id); });
if (!result.IsDeleted)
{
_dialogService.ShowWarning(result.WarningMessage);
return;
}
await RefreshFrpdCoreAsync(null, null);
_dialogService.ShowInfo("Запись удалена.");
});
}
private void DeleteFrpdvdAsync()
{
if (SelectedFrpdvd == null)
{
return;
}
var selected = SelectedFrpdvd;
if (!_dialogService.Confirm(string.Format("Удалить вид деятельности \"{0}\"?", selected.ActivityName)))
{
return;
}
RunMutationOperation(async delegate
{
var result = await Task.Run(delegate { return _service.DeleteFrpdvdItem(selected.Id); });
if (!result.IsDeleted)
{
_dialogService.ShowWarning(result.WarningMessage);
return;
}
await RefreshFrpdCoreAsync(selected.FrpdId, null);
_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 void EditFrpdAsync()
{
if (SelectedFrpd == null)
{
return;
}
var result = _dialogService.ShowFrpdEditDialog(CloneFrpd(SelectedFrpd), false, _frpdCache.ToList(), _service);
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
await Task.Run(delegate { _service.UpdateFrpdItem(result); });
await RefreshFrpdCoreAsync(result.Id, SelectedFrpdvd == null ? (int?)null : SelectedFrpdvd.Id);
_dialogService.ShowInfo("Запись обновлена.");
});
}
private void EditFrpdvdAsync()
{
if (SelectedFrpdvd == null)
{
return;
}
var result = _dialogService.ShowFrpdvdEditDialog(CloneFrpdvd(SelectedFrpdvd), false, FrpdvdItems.ToList(), _service);
if (result == null)
{
return;
}
RunMutationOperation(async delegate
{
await Task.Run(delegate { _service.UpdateFrpdvdItem(result); });
await RefreshFrpdCoreAsync(result.FrpdId, result.Id);
_dialogService.ShowInfo("Запись обновлена.");
});
}
private string[] GetSearchTokens()
{
return (SearchText ?? string.Empty)
.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(delegate(string token) { return token.Trim().ToUpperInvariant(); })
.Where(delegate(string token) { return token.Length > 0; })
.ToArray();
}
private void LoadFrpdvdForSelection()
{
if (!IsBusy)
{
RunBusyOperation(async delegate
{
if (SelectedFrpd == null)
{
FrpdvdItems.Clear();
SelectedFrpdvd = null;
UpdateStatus();
return;
}
await RefreshFrpdvdCoreAsync(SelectedFrpd.Id, null);
});
}
}
private bool MatchesSearch(FrpdDirectoryItem item)
{
if (item == null)
{
return false;
}
var tokens = GetSearchTokens();
if (tokens.Length == 0)
{
return true;
}
var haystack = string.Join(
" ",
new[]
{
item.Id.ToString(),
item.Name,
item.ParentName,
item.LocalCode,
item.Guid,
item.ActivityNames
}
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); }))
.ToUpperInvariant();
return tokens.All(delegate(string token) { return haystack.IndexOf(token, StringComparison.Ordinal) >= 0; });
}
private async Task RefreshFrpdCoreAsync(int? frpdIdToSelect, int? frpdvdIdToSelect)
{
var currentFrpdId = SelectedFrpd == null ? (int?)null : SelectedFrpd.Id;
_frpdCache = (await Task.Run(delegate { return _service.LoadFrpdItems(); })).ToList();
ApplyFrpdFilter(frpdIdToSelect.HasValue ? frpdIdToSelect : currentFrpdId);
if (SelectedFrpd == null)
{
FrpdvdItems.Clear();
SelectedFrpdvd = null;
UpdateStatus();
return;
}
await RefreshFrpdvdCoreAsync(SelectedFrpd.Id, frpdvdIdToSelect);
UpdateStatus();
}
private async Task RefreshFrpdvdCoreAsync(int frpdId, int? frpdvdIdToSelect)
{
var items = await Task.Run(delegate { return _service.LoadFrpdvdItems(frpdId); });
FrpdvdItems.Clear();
foreach (var item in items)
{
FrpdvdItems.Add(item);
}
SelectedFrpdvd = frpdvdIdToSelect.HasValue
? FrpdvdItems.FirstOrDefault(delegate(FrpdvdDirectoryItem item) { return item.Id == frpdvdIdToSelect.Value; })
: FrpdvdItems.FirstOrDefault();
UpdateStatus();
}
private void RaiseCommandStates()
{
((RelayCommand)AddFrpdCommand).RaiseCanExecuteChanged();
((RelayCommand)EditFrpdCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteFrpdCommand).RaiseCanExecuteChanged();
((RelayCommand)AddFrpdvdCommand).RaiseCanExecuteChanged();
((RelayCommand)EditFrpdvdCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteFrpdvdCommand).RaiseCanExecuteChanged();
((RelayCommand)RefreshCommand).RaiseCanExecuteChanged();
}
private void RefreshAsync()
{
RunBusyOperation(async delegate { await RefreshFrpdCoreAsync(SelectedFrpd == null ? (int?)null : SelectedFrpd.Id, SelectedFrpdvd == null ? (int?)null : SelectedFrpdvd.Id); });
}
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 searchText = string.IsNullOrWhiteSpace(SearchText) ? null : SearchText.Trim();
StatusText = string.Format(
"{0}Подразделений: {1}/{2}. Видов деятельности: {3}.",
string.IsNullOrWhiteSpace(searchText) ? string.Empty : string.Format("Поиск: \"{0}\". ", searchText),
FrpdItems.Count,
_frpdCache.Count,
FrpdvdItems.Count);
}
}
}