fix: AmineContentSeparatorCalibrationView

This commit is contained in:
2026-03-04 10:01:58 +03:00
parent cd974ebcca
commit a2f99cc376
2 changed files with 130 additions and 67 deletions
@@ -28,9 +28,9 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
private CancellationTokenSource? _captureImagesTaskCts = null; private CancellationTokenSource? _captureImagesTaskCts = null;
[ObservableProperty] private ObservableCollection<SeparatorRecord> _records; [ObservableProperty] private ObservableCollection<SeparatorRecord> _records;
[ObservableProperty] private SeparatorRecord _currentRecord; [ObservableProperty] private SeparatorRecord? _selectedRecord;
[ObservableProperty] private SeparatorRecord _editingRecord;
[ObservableProperty] private bool _isMenuOpen = false; [ObservableProperty] private bool _isMenuOpen = false;
[ObservableProperty] private bool _isNewRecord = false;
[ObservableProperty] private int _mainSectionsCurrentIndex = 0; [ObservableProperty] private int _mainSectionsCurrentIndex = 0;
[ObservableProperty] private bool _mainSectionCanScrollBackward = false; [ObservableProperty] private bool _mainSectionCanScrollBackward = false;
@@ -59,31 +59,33 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
Records = new ObservableCollection<SeparatorRecord>(_context.SeparatorRecords.Include(r => r.Images)); Records = new ObservableCollection<SeparatorRecord>(_context.SeparatorRecords.Include(r => r.Images));
if (Records.Count() > 0) SelectedRecord = Records.FirstOrDefault();
{ if (SelectedRecord is null)
CurrentRecord = Records.First(); EditingRecord = new()
IsNewRecord = false;
}
else
{
CurrentRecord = new SeparatorRecord()
{ {
Type = "", Type = "",
Batch = "", Batch = "",
Images = new() Images = new()
}; };
IsNewRecord = true; else
} EditingRecord = CopyRecord(SelectedRecord);
_logger.LogInformation("Initialized"); _logger.LogInformation("Initialized");
} }
partial void OnRecordsChanged(ObservableCollection<SeparatorRecord>? oldValue, ObservableCollection<SeparatorRecord> newValue) partial void OnSelectedRecordChanged(SeparatorRecord? value)
{ {
oldValue?.CollectionChanged -= OnRecordsCollectionChanged; if (SelectedRecord is null)
newValue?.CollectionChanged += OnRecordsCollectionChanged; EditingRecord = new()
{
Type = "",
Batch = "",
Images = new()
};
else
EditingRecord = CopyRecord(SelectedRecord);
} }
partial void OnCurrentRecordChanged(SeparatorRecord value) partial void OnEditingRecordChanged(SeparatorRecord value)
{ {
var images = value.Images var images = value.Images
.ToAsyncEnumerable() .ToAsyncEnumerable()
@@ -92,40 +94,19 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
.Select(kv => new KeyValuePair<IImage, ImageRecord>(new Bitmap(kv.Key!), kv.Value)); .Select(kv => new KeyValuePair<IImage, ImageRecord>(new Bitmap(kv.Key!), kv.Value));
Images = new(images.ToBlockingEnumerable()); Images = new(images.ToBlockingEnumerable());
IsNewRecord = _context.Entry(value).State == EntityState.Detached;
}
private void OnRecordsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs ea)
{
Console.WriteLine($"RecordsCollectionChanged {ea.Action}");
} }
[RelayCommand] private void ToggleMenu() => IsMenuOpen = !IsMenuOpen; [RelayCommand] private void ToggleMenu() => IsMenuOpen = !IsMenuOpen;
[RelayCommand] private void CloseMenu() => IsMenuOpen = false; [RelayCommand] private void CloseMenu() => IsMenuOpen = false;
[RelayCommand] [RelayCommand] private void CreateRecord() => SelectedRecord = null;
private void CreateRecord()
{
var record = new SeparatorRecord()
{
Type = "",
Batch = "",
Images = new()
};
CurrentRecord = record;
IsNewRecord = true;
}
[RelayCommand] [RelayCommand]
private void DeleteRecord() private void DeleteRecord()
{ {
var deletedRecord = CurrentRecord; var deletedRecord = SelectedRecord;
var deletedIsNewRecord = IsNewRecord;
IsNewRecord = true;
CreateRecord(); CreateRecord();
if (deletedRecord is not null)
if (!deletedIsNewRecord)
{ {
Records.Remove(deletedRecord); Records.Remove(deletedRecord);
_context.SeparatorRecords.Remove(deletedRecord); _context.SeparatorRecords.Remove(deletedRecord);
@@ -136,26 +117,89 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
[RelayCommand] [RelayCommand]
private void SaveRecord() private void SaveRecord()
{ {
for (int i = 0; i < CurrentRecord.Images.Count(); i++) if (SelectedRecord is null)
{ {
var image = CurrentRecord.Images[i]; var newEntity = CopyRecord(EditingRecord);
if (_context.Entry(image).State == EntityState.Detached)
for (int i = 0; i < newEntity.Images.Count(); i++)
{ {
var image = newEntity.Images[i];
if (_context.Entry(image).State is not EntityState.Detached)
continue;
var attachedImage = _context.ImageRecords.Add(image); var attachedImage = _context.ImageRecords.Add(image);
CurrentRecord.Images.RemoveAt(i); newEntity.Images.RemoveAt(i);
CurrentRecord.Images.Insert(i, attachedImage.Entity); newEntity.Images.Insert(i, attachedImage.Entity);
} }
} if (_context.Entry(newEntity).State is EntityState.Detached)
if (_context.Entry(CurrentRecord).State == EntityState.Detached)
{ {
var attachedRecord = _context.SeparatorRecords.Add(CurrentRecord); var attachedRecord = _context.SeparatorRecords.Add(newEntity);
CurrentRecord = attachedRecord.Entity; newEntity = attachedRecord.Entity;
} }
if (IsNewRecord)
Records.Add(CurrentRecord);
_context.SaveChanges(); _context.SaveChanges();
IsNewRecord = false;
Records.Add(newEntity);
SelectedRecord = newEntity;
}
else
{
SelectedRecord.Type = EditingRecord.Type;
SelectedRecord.Batch = EditingRecord.Batch;
var imagesToRemove = SelectedRecord.Images
.Where(e => EditingRecord.Images.All(i => i.Id != e.Id))
.ToList();
foreach (var image in imagesToRemove)
SelectedRecord.Images.Remove(image);
foreach (var editedImage in EditingRecord.Images)
{
var existing = EditingRecord.Images
.FirstOrDefault(i => i.Id == editedImage.Id);
if (existing is null)
{
SelectedRecord.Images.Add(
new ImageRecord
{
ImagePath = editedImage.ImagePath,
VisibleIntensity = editedImage.VisibleIntensity,
Uv365Intensity = editedImage.Uv365Intensity,
Uv254Intensity = editedImage.Uv254Intensity
}
);
}
else
{
existing.ImagePath = editedImage.ImagePath;
existing.VisibleIntensity = editedImage.VisibleIntensity;
existing.Uv365Intensity = editedImage.Uv365Intensity;
existing.Uv254Intensity = editedImage.Uv254Intensity;
}
}
for (int i = 0; i < SelectedRecord.Images.Count(); i++)
{
var image = SelectedRecord.Images[i];
if (_context.Entry(image).State is not EntityState.Detached)
continue;
var attachedImage = _context.ImageRecords.Add(image);
SelectedRecord.Images.RemoveAt(i);
SelectedRecord.Images.Insert(i, attachedImage.Entity);
}
if (_context.Entry(SelectedRecord).State is EntityState.Detached)
{
var attachedRecord = _context.SeparatorRecords.Add(SelectedRecord);
var index = Records.IndexOf(SelectedRecord);
Records[index] = attachedRecord.Entity;
SelectedRecord = attachedRecord.Entity;
}
_context.SaveChanges();
}
} }
[RelayCommand] private void SwitchMainSection() => MainSectionsCurrentIndex = MainSectionsCurrentIndex == 0 ? 1 : 0; [RelayCommand] private void SwitchMainSection() => MainSectionsCurrentIndex = MainSectionsCurrentIndex == 0 ? 1 : 0;
@@ -169,7 +213,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
_captureImagesTaskCts = new CancellationTokenSource(); _captureImagesTaskCts = new CancellationTokenSource();
var cancellationToken = _captureImagesTaskCts.Token; var cancellationToken = _captureImagesTaskCts.Token;
CaptureImagesTask = new Task(async () => CaptureImagesTask = Task.Run(async () =>
{ {
_illuminatorService.TurnOn(); _illuminatorService.TurnOn();
(double visible, double uv365, double uv254)[] intensities = (double visible, double uv365, double uv254)[] intensities =
@@ -196,6 +240,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
foreach (var (i, intensity) in intensities.Enumerate()) foreach (var (i, intensity) in intensities.Enumerate())
{ {
_logger.LogInformation("Capturing images: {} / {} ({};{};{})", i + 1, intensities.Count(), intensity.visible, intensity.uv365, intensity.uv254);
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
Dispatcher.UIThread.Invoke(() => ImagesCapturingProgress = $"Получение изображений: {i + 1} / {intensities.Count()}"); Dispatcher.UIThread.Invoke(() => ImagesCapturingProgress = $"Получение изображений: {i + 1} / {intensities.Count()}");
@@ -239,8 +284,8 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
CurrentRecord.Images.Clear(); EditingRecord.Images.Clear();
CurrentRecord.Images.AddRange(imageRecords); EditingRecord.Images.AddRange(imageRecords);
Images.Clear(); Images.Clear();
Images = new(images.ToBlockingEnumerable()); Images = new(images.ToBlockingEnumerable());
@@ -264,11 +309,29 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase
}); });
} }
}, cancellationToken); }, cancellationToken);
CaptureImagesTask.Start();
} }
[RelayCommand] private void CencelImageCapturing() => _captureImagesTaskCts?.Cancel(); [RelayCommand] private void CencelImageCapturing() => _captureImagesTaskCts?.Cancel();
[RelayCommand] private void ImagesSectionPrevious() => ImagesSectionCurrentIndex--; [RelayCommand] private void ImagesSectionPrevious() => ImagesSectionCurrentIndex--;
[RelayCommand] private void ImagesSectionNext() => ImagesSectionCurrentIndex++; [RelayCommand] private void ImagesSectionNext() => ImagesSectionCurrentIndex++;
private static SeparatorRecord CopyRecord(SeparatorRecord source)
{
return new SeparatorRecord
{
Id = source.Id,
Type = source.Type,
Batch = source.Batch,
Images = source.Images
.Select(i => new ImageRecord
{
Id = i.Id,
ImagePath = i.ImagePath,
VisibleIntensity = i.VisibleIntensity,
Uv365Intensity = i.Uv365Intensity,
Uv254Intensity = i.Uv254Intensity
})
.ToList()
};
}
} }
@@ -116,7 +116,7 @@
Margin="10,0,0,0" Margin="10,0,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontSize="18" FontSize="18"
Text="{Binding CurrentRecord.Id, StringFormat='Id: {0}'}" /> Text="{Binding EditingRecord.Id, StringFormat='Id: {0}'}" />
</Grid> </Grid>
</Border> </Border>
@@ -171,7 +171,7 @@
<TextBox <TextBox
Grid.Row="1" Grid.Row="1"
Classes="singleline" Classes="singleline"
Text="{Binding CurrentRecord.Type}" Text="{Binding EditingRecord.Type}"
Watermark="Тип" /> Watermark="Тип" />
<TextBlock <TextBlock
@@ -182,7 +182,7 @@
<TextBox <TextBox
Grid.Row="3" Grid.Row="3"
Classes="singleline" Classes="singleline"
Text="{Binding CurrentRecord.Batch}" Text="{Binding EditingRecord.Batch}"
Watermark="Партия" /> Watermark="Партия" />
</Grid> </Grid>
@@ -531,7 +531,7 @@
Command="{Binding CreateRecordCommand}" Command="{Binding CreateRecordCommand}"
Content="Новая запись" /> Content="Новая запись" />
<ListBox ItemsSource="{Binding Records}" SelectedItem="{Binding CurrentRecord}"> <ListBox ItemsSource="{Binding Records}" SelectedItem="{Binding SelectedRecord}">
<ListBox.Styles> <ListBox.Styles>