using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows.Input; namespace XLAB2 { internal sealed class VerificationReportsWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; private readonly VerificationReportsService _service; private DateTime? _dateFrom; private DateTime? _dateTo; private bool _isBusy; private int _selectedCustomerId; private int _selectedMeasurementAreaId; private VerificationReportSummary _summary; private string _statusText; public VerificationReportsWindowViewModel(VerificationReportsService service, IDialogService dialogService) { _service = service; _dialogService = dialogService; CustomerItems = new ObservableCollection(); MeasurementAreaItems = new ObservableCollection(); CustomerRows = new ObservableCollection(); MeasurementAreaRows = new ObservableCollection(); Summary = new VerificationReportSummary(); CustomerItems.Add(new DirectoryLookupItem { Id = 0, Name = "Все заказчики" }); MeasurementAreaItems.Add(new DirectoryLookupItem { Id = 0, Name = "Все области измерений" }); RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; }); UpdateStatus(); } public ObservableCollection CustomerItems { get; private set; } public ObservableCollection CustomerRows { get; private set; } public DateTime? DateFrom { get { return _dateFrom; } set { if (SetProperty(ref _dateFrom, value)) { OnPropertyChanged("PeriodText"); } } } public DateTime? DateTo { get { return _dateTo; } set { if (SetProperty(ref _dateTo, value)) { OnPropertyChanged("PeriodText"); } } } public bool IsBusy { get { return _isBusy; } private set { if (SetProperty(ref _isBusy, value)) { ((RelayCommand)RefreshCommand).RaiseCanExecuteChanged(); } } } public ObservableCollection MeasurementAreaItems { get; private set; } public ObservableCollection MeasurementAreaRows { get; private set; } public string PeriodText { get { if (!DateFrom.HasValue && !DateTo.HasValue) { return "Период: все время."; } if (DateFrom.HasValue && DateTo.HasValue) { return string.Format("Период: с {0:d} по {1:d}.", DateFrom.Value, DateTo.Value); } if (DateFrom.HasValue) { return string.Format("Период: с {0:d}.", DateFrom.Value); } return string.Format("Период: по {0:d}.", DateTo.Value); } } public ICommand RefreshCommand { get; private set; } public int SelectedCustomerId { get { return _selectedCustomerId; } set { SetProperty(ref _selectedCustomerId, value); } } public int SelectedMeasurementAreaId { get { return _selectedMeasurementAreaId; } set { SetProperty(ref _selectedMeasurementAreaId, value); } } public string StatusText { get { return _statusText; } private set { SetProperty(ref _statusText, value); } } public VerificationReportSummary Summary { get { return _summary; } private set { SetProperty(ref _summary, value); } } public async Task InitializeAsync() { await ExecuteBusyOperationAsync(async delegate { await LoadFiltersAsync(); await RefreshCoreAsync(); }); } private VerificationReportFilter BuildFilter() { if (DateFrom.HasValue && DateTo.HasValue && DateFrom.Value.Date > DateTo.Value.Date) { throw new InvalidOperationException("Дата \"с\" не может быть позже даты \"по\"."); } return new VerificationReportFilter { CustomerId = SelectedCustomerId > 0 ? SelectedCustomerId : (int?)null, MeasurementAreaId = SelectedMeasurementAreaId > 0 ? SelectedMeasurementAreaId : (int?)null, DateFrom = DateFrom, DateTo = DateTo }; } private async Task ExecuteBusyOperationAsync(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 async Task LoadFiltersAsync() { var customersTask = Task.Run(delegate { return _service.LoadCustomerItems(); }); var measurementAreasTask = Task.Run(delegate { return _service.LoadMeasurementAreaItems(); }); await Task.WhenAll(customersTask, measurementAreasTask); ApplyLookupItems(CustomerItems, customersTask.Result, "Все заказчики"); ApplyLookupItems(MeasurementAreaItems, measurementAreasTask.Result, "Все области измерений"); if (!CustomerItems.Any(delegate(DirectoryLookupItem item) { return item.Id == SelectedCustomerId; })) { SelectedCustomerId = 0; } if (!MeasurementAreaItems.Any(delegate(DirectoryLookupItem item) { return item.Id == SelectedMeasurementAreaId; })) { SelectedMeasurementAreaId = 0; } } private static void ApplyLookupItems(ObservableCollection target, System.Collections.Generic.IReadOnlyList source, string allItemText) { target.Clear(); target.Add(new DirectoryLookupItem { Id = 0, Name = allItemText }); foreach (var item in source) { target.Add(item); } } private async Task RefreshCoreAsync() { var filter = BuildFilter(); var report = await Task.Run(delegate { return _service.LoadReport(filter); }); Summary = report.Summary ?? new VerificationReportSummary(); CustomerRows.Clear(); foreach (var row in report.CustomerRows ?? Array.Empty()) { CustomerRows.Add(row); } MeasurementAreaRows.Clear(); foreach (var row in report.MeasurementAreaRows ?? Array.Empty()) { MeasurementAreaRows.Add(row); } UpdateStatus(); } private async void RefreshAsync() { await ExecuteBusyOperationAsync(RefreshCoreAsync); } private void UpdateStatus() { StatusText = string.Format( "Заказчиков в своде: {0}. Видов измерений в своде: {1}. Поверено: {2}. Годен: {3}. Забракован: {4}.", CustomerRows.Count, MeasurementAreaRows.Count, Summary == null ? 0 : Summary.TotalCount, Summary == null ? 0 : Summary.GoodCount, Summary == null ? 0 : Summary.RejectedCount); } } }