using Lattice.Core.DragDrop.Services; using Lattice.UI.DragDrop.Abstractions; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System; namespace Lattice.UI.DragDrop.WinUI.Services; /// /// Сервис интеграции Drag & Drop с WinUI приложением. /// public class WinUIDragDropIntegrationService : IDisposable { private readonly IDragDropService _dragDropService; private readonly IDragVisualProvider _dragVisualProvider; private readonly Canvas _overlayCanvas; private readonly Window _window; private object? _currentDragVisual; private bool _disposed; /// /// Инициализирует новый экземпляр класса . /// public WinUIDragDropIntegrationService( Window window, IDragDropService dragDropService, IDragVisualProvider dragVisualProvider) { _window = window ?? throw new ArgumentNullException(nameof(window)); _dragDropService = dragDropService ?? throw new ArgumentNullException(nameof(dragDropService)); _dragVisualProvider = dragVisualProvider ?? throw new ArgumentNullException(nameof(dragVisualProvider)); // Создаем оверлейный Canvas для визуальных элементов _overlayCanvas = new Canvas { IsHitTestVisible = false, Background = null }; // Подписываемся на события перетаскивания SubscribeToEvents(); } /// /// Встраивает оверлей в указанный контейнер. /// public void AttachToContainer(Panel container) { if (container == null) throw new ArgumentNullException(nameof(container)); // Убеждаемся, что оверлей находится поверх всех элементов Canvas.SetZIndex(_overlayCanvas, int.MaxValue); container.Children.Add(_overlayCanvas); } private void SubscribeToEvents() { _dragDropService.DragStarted += OnDragStarted; _dragDropService.DragUpdated += OnDragUpdated; _dragDropService.DragCompleted += OnDragCompleted; _dragDropService.DragCancelled += OnDragCancelled; } private void UnsubscribeFromEvents() { _dragDropService.DragStarted -= OnDragStarted; _dragDropService.DragUpdated -= OnDragUpdated; _dragDropService.DragCompleted -= OnDragCompleted; _dragDropService.DragCancelled -= OnDragCancelled; } private void OnDragStarted(object? sender, DragStartedEventArgs e) { // Создаем визуальное представление _currentDragVisual = _dragVisualProvider.CreateDragVisual( e.DragInfo, e.StartPosition); // Добавляем на оверлей if (_currentDragVisual is UIElement element) { _overlayCanvas.Children.Add(element); } } private void OnDragUpdated(object? sender, DragUpdatedEventArgs e) { if (_currentDragVisual != null) { _dragVisualProvider.UpdateDragVisualPosition(_currentDragVisual, e.Position); } } private void OnDragCompleted(object? sender, DragCompletedEventArgs e) { CleanupDragVisual(); } private void OnDragCancelled(object? sender, DragCancelledEventArgs e) { CleanupDragVisual(); } private void CleanupDragVisual() { if (_currentDragVisual != null) { _dragVisualProvider.ReleaseDragVisual(_currentDragVisual); _currentDragVisual = null; } } /// public void Dispose() { if (!_disposed) { UnsubscribeFromEvents(); CleanupDragVisual(); if (_overlayCanvas.Parent is Panel parent) { parent.Children.Remove(_overlayCanvas); } _disposed = true; } GC.SuppressFinalize(this); } }