using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Drawing.Printing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; using System.Windows.Input; using System.Runtime.CompilerServices; using System.Threading; using XLIMS.MVVM.Base; using XLIMS.DATA.Models; using XLIMS.CONTRACT; namespace XLIMS.PSV.ViewModels { public class BrowseTprzViewModel : ViewModelBase, IDataErrorInfo, IDisposable { private readonly ILimsService _limsService; private readonly ObservableCollection _allTprz = new(); private Tprz? _currentTprz = null; private string _search = string.Empty; private string _serial = string.Empty; private bool _isValid; private CancellationTokenSource? _searchCts; private CancellationTokenSource? _loadCts; private string _lastFilter = string.Empty; public BrowseTprzViewModel(ILimsService limsService) { _limsService = limsService; AllTPRZView = CollectionViewSource.GetDefaultView(_allTprz); AllTPRZView.Filter = TprzFilter; LoadTPRZAsync(); } private async Task LoadTPRZAsync() { _loadCts?.Cancel(); _loadCts = new CancellationTokenSource(); try { _allTprz.Clear(); var items = await _limsService.Tprzs.GetAllAsync(); foreach (var item in items) _allTprz.Add(item); AllTPRZView.Refresh(); } catch (OperationCanceledException) { } catch (Exception) { // Логирование или отображение ошибки пользователю } } public ICollectionView AllTPRZView { get; } public Tprz? CurrentTPRZ { get => _currentTprz; set { _currentTprz = value; OnPropertyChanged(); } } public string Search { get => _search; set { _search = value ?? string.Empty; DebouncedRefresh(); OnPropertyChanged(); } } private async void DebouncedRefresh() { _searchCts?.Cancel(); _searchCts = new CancellationTokenSource(); try { await Task.Delay(300, _searchCts.Token); AllTPRZView.Refresh(); } catch (TaskCanceledException) { } } public string Serial { get => _serial; set { _serial = value?.Trim() ?? string.Empty; OnPropertyChanged(); } } private bool TprzFilter(object obj) { if (obj is not Tprz tprz) return false; var filter = Search?.Trim() ?? string.Empty; if (_lastFilter != filter) _lastFilter = filter; if (string.IsNullOrWhiteSpace(_lastFilter)) return true; return (tprz.Dpzn?.Contains(_lastFilter, StringComparison.OrdinalIgnoreCase) == true) || (tprz.IdtipNavigation.Tp?.Contains(_lastFilter, StringComparison.OrdinalIgnoreCase) == true) || (tprz.IdtipNavigation?.IdspnmtpNavigation?.Nmtp?.Contains(_lastFilter, StringComparison.OrdinalIgnoreCase) == true); } private RelayCommand? _saveCommand; public ICommand SaveCommand => _saveCommand ??= new RelayCommand(_ => Save(), _ => _isValid && CurrentTPRZ != null); private void Save() { } private new void OnPropertyChanged([CallerMemberName] string propertyName = "") { base.OnPropertyChanged(propertyName); if (propertyName == nameof(Serial) || propertyName == nameof(CurrentTPRZ)) CommandManager.InvalidateRequerySuggested(); } #region IDataErrorInfo public string Error => string.Empty; private void ValidateAll() { _isValid = Validate(); CommandManager.InvalidateRequerySuggested(); } public string this[string columnName] { get { string msg = string.Empty; switch (columnName) { case nameof(Serial): if (string.IsNullOrWhiteSpace(Serial)) msg = "Поле не может быть пустым!"; break; } ValidateAll(); return msg; } } private bool Validate() { // Добавьте комплексную валидацию всех нужных полей return !string.IsNullOrWhiteSpace(Serial); } #endregion private bool _disposed = false; public void Dispose() { if (_disposed) return; _disposed = true; _searchCts?.Dispose(); _loadCts?.Dispose(); } } }