using System; using System.Collections.Generic; using System.Linq; using System.Windows.Input; namespace XLAB2 { internal sealed class TipsEditWindowViewModel : ObservableObject { private readonly IReadOnlyList _existingItems; private int _categoryId; private int _designId; private int _instrumentNameId; private bool? _isMkPrimaryOnly; private bool? _isSpecialPurpose; private int _measurementAreaId; private string _metrControlCode; private string _notes; private string _registryPeriodMonthsText; private string _registryTypeNumber; private string _serviceLifeYearsText; private string _typeName; private string _validationMessage; private string _vniimsTypeCodeText; public TipsEditWindowViewModel(TipsDirectoryItem seed, bool isNew, IReadOnlyList existingItems, TypeSizeDirectoryService service) { var source = seed ?? new TipsDirectoryItem(); _existingItems = existingItems ?? Array.Empty(); Id = source.Id; IsNew = isNew; MeasurementAreas = service.LoadSpoiReferences(); InstrumentNames = service.LoadSpnmtpReferences(); Categories = WithEmpty(service.LoadSpktReferences()); Designs = WithEmpty(service.LoadSpkiReferences()); MeasurementAreaId = source.MeasurementAreaId; InstrumentNameId = source.InstrumentNameId; CategoryId = source.CategoryId ?? 0; DesignId = source.DesignId ?? 0; TypeName = source.TypeName ?? string.Empty; ServiceLifeYearsText = source.ServiceLifeYears.HasValue ? source.ServiceLifeYears.Value.ToString() : string.Empty; RegistryPeriodMonthsText = source.RegistryPeriodMonths.HasValue ? source.RegistryPeriodMonths.Value.ToString() : string.Empty; RegistryTypeNumber = source.RegistryTypeNumber ?? string.Empty; VniimsTypeCodeText = source.VniimsTypeCode.HasValue ? source.VniimsTypeCode.Value.ToString() : string.Empty; MetrControlCode = source.MetrControlCode ?? string.Empty; Notes = source.Notes ?? string.Empty; IsSpecialPurpose = source.IsSpecialPurpose; IsMkPrimaryOnly = source.IsMkPrimaryOnly; ConfirmCommand = new RelayCommand(Confirm); CancelCommand = new RelayCommand(Cancel); } public event EventHandler CloseRequested; public ICommand CancelCommand { get; private set; } public IReadOnlyList Categories { get; private set; } public ICommand ConfirmCommand { get; private set; } public IReadOnlyList Designs { get; private set; } public int Id { get; private set; } public IReadOnlyList InstrumentNames { get; private set; } public bool IsNew { get; private set; } public IReadOnlyList MeasurementAreas { get; private set; } public int MeasurementAreaId { get { return _measurementAreaId; } set { SetProperty(ref _measurementAreaId, value); } } public int InstrumentNameId { get { return _instrumentNameId; } set { SetProperty(ref _instrumentNameId, value); } } public int CategoryId { get { return _categoryId; } set { SetProperty(ref _categoryId, value); } } public int DesignId { get { return _designId; } set { SetProperty(ref _designId, value); } } public string TypeName { get { return _typeName; } set { SetProperty(ref _typeName, value); } } public string ServiceLifeYearsText { get { return _serviceLifeYearsText; } set { SetProperty(ref _serviceLifeYearsText, value); } } public string RegistryPeriodMonthsText { get { return _registryPeriodMonthsText; } set { SetProperty(ref _registryPeriodMonthsText, value); } } public string RegistryTypeNumber { get { return _registryTypeNumber; } set { SetProperty(ref _registryTypeNumber, value); } } public string VniimsTypeCodeText { get { return _vniimsTypeCodeText; } set { SetProperty(ref _vniimsTypeCodeText, value); } } public string MetrControlCode { get { return _metrControlCode; } set { SetProperty(ref _metrControlCode, value); } } public string Notes { get { return _notes; } set { SetProperty(ref _notes, value); } } public bool? IsSpecialPurpose { get { return _isSpecialPurpose; } set { SetProperty(ref _isSpecialPurpose, value); } } public bool? IsMkPrimaryOnly { get { return _isMkPrimaryOnly; } set { SetProperty(ref _isMkPrimaryOnly, value); } } public string Title { get { return IsNew ? "Новый тип СИ" : "Редактирование типа СИ"; } } public string ValidationMessage { get { return _validationMessage; } private set { SetProperty(ref _validationMessage, value); } } public TipsDirectoryItem ToResult() { return new TipsDirectoryItem { Id = Id, MeasurementAreaId = MeasurementAreaId, InstrumentNameId = InstrumentNameId, CategoryId = CategoryId > 0 ? (int?)CategoryId : null, DesignId = DesignId > 0 ? (int?)DesignId : null, TypeName = Normalize(TypeName), ServiceLifeYears = ParseNullableInt(ServiceLifeYearsText), RegistryPeriodMonths = ParseNullableInt(RegistryPeriodMonthsText), RegistryTypeNumber = Normalize(RegistryTypeNumber), VniimsTypeCode = ParseNullableInt(VniimsTypeCodeText), MetrControlCode = Normalize(MetrControlCode), Notes = Normalize(Notes), IsSpecialPurpose = IsSpecialPurpose, IsMkPrimaryOnly = IsMkPrimaryOnly }; } private void Cancel(object parameter) { RaiseCloseRequested(false); } private void Confirm(object parameter) { if (MeasurementAreaId <= 0) { ValidationMessage = "Укажите область измерений."; return; } if (InstrumentNameId <= 0) { ValidationMessage = "Укажите наименование типа СИ."; return; } var normalizedTypeName = Normalize(TypeName); if (string.IsNullOrWhiteSpace(normalizedTypeName)) { ValidationMessage = "Укажите тип СИ."; return; } if (normalizedTypeName.Length > TipsDirectoryRules.TypeNameMaxLength) { ValidationMessage = string.Format("Тип СИ не должен превышать {0} символов.", TipsDirectoryRules.TypeNameMaxLength); return; } int? parsedValue; if (!TryParseNullableInt(ServiceLifeYearsText, out parsedValue)) { ValidationMessage = "Срок службы должен быть целым числом."; return; } if (!TryParseNullableInt(RegistryPeriodMonthsText, out parsedValue)) { ValidationMessage = "МПИ по Госреестру должен быть целым числом."; return; } if (!TryParseNullableInt(VniimsTypeCodeText, out parsedValue)) { ValidationMessage = "Код ВНИИМС должен быть целым числом."; return; } var normalizedRegistryNumber = Normalize(RegistryTypeNumber); if (!string.IsNullOrWhiteSpace(normalizedRegistryNumber) && normalizedRegistryNumber.Length > TipsDirectoryRules.RegistryTypeNumberMaxLength) { ValidationMessage = string.Format("Номер по Госреестру не должен превышать {0} символов.", TipsDirectoryRules.RegistryTypeNumberMaxLength); return; } var normalizedMetrControlCode = Normalize(MetrControlCode); if (!string.IsNullOrWhiteSpace(normalizedMetrControlCode) && normalizedMetrControlCode.Length > TipsDirectoryRules.MetrControlCodeMaxLength) { ValidationMessage = string.Format("Код АИС \"Метрконтроль\" не должен превышать {0} символов.", TipsDirectoryRules.MetrControlCodeMaxLength); return; } var duplicate = _existingItems.FirstOrDefault(delegate(TipsDirectoryItem item) { return item != null && item.Id != Id && item.InstrumentNameId == InstrumentNameId && string.Equals(Normalize(item.TypeName), normalizedTypeName, StringComparison.OrdinalIgnoreCase); }); if (duplicate != null) { ValidationMessage = string.Format("Тип СИ \"{0}\" уже существует для выбранного наименования типа СИ.", normalizedTypeName); return; } ValidationMessage = string.Empty; RaiseCloseRequested(true); } private static IReadOnlyList WithEmpty(IReadOnlyList source) { return new[] { new DirectoryLookupItem { Id = 0, Name = string.Empty } }.Concat(source ?? Array.Empty()).ToList(); } private static string Normalize(string value) { return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim(); } private static int? ParseNullableInt(string value) { int? parsedValue; return TryParseNullableInt(value, out parsedValue) ? parsedValue : (int?)null; } private static bool TryParseNullableInt(string value, out int? result) { if (string.IsNullOrWhiteSpace(value)) { result = null; return true; } int parsed; if (int.TryParse(value.Trim(), out parsed)) { result = parsed; return true; } result = null; return false; } private void RaiseCloseRequested(bool? dialogResult) { var handler = CloseRequested; if (handler != null) { handler(this, dialogResult); } } } }