/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.App/ViewModels/MeasurementsViewModel.cs
187 строк
5 KB
docNemo
Вкладка деталей выкройки, создание документа и пересчёт производных вкладок
09 авг 2026, 14:03
09 авг 2026, 14:03
dd71293
Код
Авторство
О чём код?
using System; using System.Collections.ObjectModel; using System.Linq; using ClothesGraph.Geometry; using ClothesGraph.Model; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace ClothesGraph.App.ViewModels; /// <summary> /// Редактирование мерок и размерной сетки. /// </summary> /// <remarks> /// Сетка показывается по одному размеру за раз, а не таблицей «мерки на размеры». /// Столбцов в такой таблице столько же, сколько размеров в ряду, и при десятке /// размеров она перестаёт читаться; переключение размера решает ту же задачу /// без потери обзора. /// </remarks> public sealed partial class MeasurementsViewModel : ObservableObject { private readonly PatternDocument _document; [ObservableProperty] private string? _selectedSize; [ObservableProperty] private string _newSizeName = string.Empty; [ObservableProperty] private string _completenessSummary = string.Empty; public MeasurementsViewModel(PatternDocument document) { _document = document; Sizes = new ObservableCollection<string>(document.Sizes.Sizes); Rows = []; _selectedSize = document.Sizes.BaseSize; ReloadRows(); } public ObservableCollection<string> Sizes { get; } public ObservableCollection<MeasurementRowViewModel> Rows { get; } public ObservableCollection<UnitOption> Units { get; } = [ UnitOption.For(LengthUnit.Millimetre), UnitOption.For(LengthUnit.Centimetre), UnitOption.For(LengthUnit.Inch) ]; public UnitOption DisplayUnit { get => Units.First(option => option.Unit == _document.DisplayUnit); set { if (_document.DisplayUnit == value.Unit) return; _document.DisplayUnit = value.Unit; _document.MarkModified(); OnPropertyChanged(); RefreshRows(); } } public string BaseSize => _document.Sizes.BaseSize; [RelayCommand] private void AddMeasurement() { var name = UniqueName(); _document.Measurements.Add(name, Length.Zero); _document.MarkModified(); ReloadRows(); } [RelayCommand] private void RemoveMeasurement(MeasurementRowViewModel? row) { if (row is null) return; _document.Measurements.Remove(row.Id); _document.MarkModified(); Rows.Remove(row); NotifyCompletenessChanged(); } [RelayCommand] private void AddSize() { if (string.IsNullOrWhiteSpace(NewSizeName)) return; var name = NewSizeName.Trim(); if (_document.Sizes.ContainsSize(name)) return; _document.Sizes.AddSize(name); _document.MarkModified(); Sizes.Add(name); NewSizeName = string.Empty; SelectedSize = name; } [RelayCommand] private void RemoveSize() { if (SelectedSize is null || SelectedSize == _document.Sizes.BaseSize) return; var removed = SelectedSize; _document.Sizes.RemoveSize(removed); _document.MarkModified(); Sizes.Remove(removed); SelectedSize = _document.Sizes.BaseSize; } /// <summary>Делает выбранный размер базовым: в нём строится конструкция.</summary> [RelayCommand] private void MakeSizeBase() { if (SelectedSize is null) return; _document.Sizes.SetBaseSize(SelectedSize); _document.MarkModified(); OnPropertyChanged(nameof(BaseSize)); RefreshRows(); } partial void OnSelectedSizeChanged(string? value) { if (value is not null) RefreshRows(); } private void ReloadRows() { Rows.Clear(); var size = SelectedSize ?? _document.Sizes.BaseSize; foreach (var measurement in _document.Measurements.Measurements.OrderBy(m => m.DisplayName)) Rows.Add(new MeasurementRowViewModel(_document, this, measurement, size)); NotifyCompletenessChanged(); } private void RefreshRows() { var size = SelectedSize ?? _document.Sizes.BaseSize; foreach (var row in Rows) row.Refresh(size); NotifyCompletenessChanged(); } internal void NotifyCompletenessChanged() { var incomplete = _document.Sizes.FindIncompleteSizes(_document.Measurements); CompletenessSummary = incomplete.Count == 0 ? "Все размеры заполнены" : "Не заполнены: " + string.Join(", ", incomplete.Select(resolution => $"{resolution.Size} ({resolution.Missing.Count})")); } private string UniqueName() { const string prefix = "Мерка"; for (var index = 1; ; index++) { var candidate = $"{prefix} {index}"; if (_document.Measurements.FindByName(candidate) is null) return candidate; } } }