using Lattice.Core.DragDrop.Factories;
using Lattice.Core.DragDrop.Services;
using Lattice.UI.DragDrop.WinUI.Behaviors;
using Lattice.UI.DragDrop.WinUI.Controls;
using Lattice.UI.DragDrop.WinUI.Services;
using Microsoft.UI.Xaml;
using System;
namespace Lattice.UI.DragDrop.WinUI.Factories;
///
/// Фабрика для создания компонентов системы перетаскивания WinUI.
/// Предоставляет методы для быстрой настройки drag-and-drop в приложениях WinUI.
///
///
/// Эта фабрика упрощает интеграцию системы перетаскивания в WinUI приложения,
/// предоставляя готовые методы для наиболее распространенных сценариев использования.
///
public static class WinUIDragDropFactory
{
#region Основные компоненты
///
/// Создает и инициализирует менеджер перетаскивания для WinUI окна.
///
///
/// Окно WinUI, для которого создается менеджер перетаскивания.
///
///
/// Инициализированный экземпляр .
///
///
/// Выбрасывается, когда равен null.
///
///
/// Этот метод создает менеджер перетаскивания и настраивает его для работы с указанным окном.
/// Менеджер автоматически создает оверлей для визуальных элементов и подписывается на события.
///
///
///
/// public partial class MainWindow : Window
/// {
/// private WinUIDragDropManager _dragDropManager;
///
/// public MainWindow()
/// {
/// InitializeComponent();
/// _dragDropManager = WinUIDragDropFactory.CreateManager(this);
/// }
/// }
///
///
public static WinUIDragDropManager CreateManager(Window window)
{
if (window == null)
throw new ArgumentNullException(nameof(window));
var manager = WinUIDragDropManager.Instance;
manager.Initialize(window);
return manager;
}
///
/// Создает и инициализирует менеджер перетаскивания с пользовательскими настройками.
///
///
/// Окно WinUI, для которого создается менеджер перетаскивания.
///
///
/// Делегат для настройки менеджера перед инициализацией.
///
///
/// Инициализированный экземпляр .
///
///
/// Этот метод позволяет настроить параметры менеджера (например, смещение визуального элемента)
/// перед его инициализацией.
///
public static WinUIDragDropManager CreateManager(Window window, Action configure)
{
if (window == null)
throw new ArgumentNullException(nameof(window));
var manager = WinUIDragDropManager.Instance;
configure?.Invoke(manager);
manager.Initialize(window);
return manager;
}
///
/// Создает хост для визуальных элементов перетаскивания.
///
///
/// Окно, к которому будет привязан хост.
///
///
/// Экземпляр , готовый к использованию.
///
///
/// Хост управляет отображением визуальных элементов (drag-визуализация, drop-превью)
/// на оверлейном слое поверх основного содержимого окна.
///
public static WinUIDragDropHost CreateHost(Window window)
{
if (window == null)
throw new ArgumentNullException(nameof(window));
var host = new WinUIDragDropHost();
host.Initialize(window);
return host;
}
#endregion
#region Поведения (Behaviors)
///
/// Создает поведение источника перетаскивания для элемента WinUI.
///
///
/// Сервис перетаскивания, который будет управлять операциями.
///
///
/// Хост для отображения визуальных элементов.
///
///
/// Экземпляр , готовый к прикреплению к элементу.
///
///
/// Выбрасывается, если любой из параметров равен null.
///
///
/// Созданное поведение необходимо прикрепить к элементу с помощью метода .
///
public static WinUIDragSourceBehavior CreateDragSourceBehavior(
IDragDropService dragDropService,
WinUIDragDropHost host)
{
if (dragDropService == null)
throw new ArgumentNullException(nameof(dragDropService));
if (host == null)
throw new ArgumentNullException(nameof(host));
return new WinUIDragSourceBehavior(dragDropService, host);
}
///
/// Создает поведение цели сброса для элемента WinUI.
///
///
/// Сервис перетаскивания, который будет управлять операциями.
///
///
/// Хост для отображения визуальных элементов.
///
///
/// Экземпляр , готовый к прикреплению к элементу.
///
///
/// Выбрасывается, если любой из параметров равен null.
///
///
/// Созданное поведение необходимо прикрепить к элементу с помощью метода .
///
public static WinUIDropTargetBehavior CreateDropTargetBehavior(
IDragDropService dragDropService,
WinUIDragDropHost host)
{
if (dragDropService == null)
throw new ArgumentNullException(nameof(dragDropService));
if (host == null)
throw new ArgumentNullException(nameof(host));
return new WinUIDropTargetBehavior(dragDropService, host);
}
#endregion
#region Визуальные элементы
///
/// Создает визуальный элемент для отображения во время перетаскивания.
///
///
/// Данные, которые будут отображены в визуальном элементе.
///
///
/// Прозрачность элемента (от 0.0 до 1.0).
///
///
/// Экземпляр , настроенный для отображения указанных данных.
///
///
/// Созданный элемент можно использовать с методом
/// для отображения во время операции перетаскивания.
///
public static DragAdorner CreateDragAdorner(object dragData, double opacity = 0.8)
{
return new DragAdorner
{
DragData = dragData,
Opacity = opacity
};
}
///
/// Создает элемент предварительного просмотра для области сброса.
///
///
/// Цвет подсветки области. Если не указан, используется цвет из ресурсов темы.
///
///
/// Толщина границы подсветки.
///
///
/// Экземпляр , готовый к отображению.
///
///
/// Этот элемент используется для визуального указания области, на которую можно сбросить данные.
///
public static DropPreviewAdorner CreateDropPreviewAdorner(
Windows.UI.Color? color = null,
double thickness = 2.0)
{
var adorner = new DropPreviewAdorner
{
PreviewThickness = thickness
};
if (color.HasValue)
{
adorner.PreviewColor = color.Value;
}
return adorner;
}
#endregion
#region Готовые конфигурации для типовых сценариев
///
/// Создает полную систему перетаскивания для WinUI приложения.
///
///
/// Главное окно приложения.
///
///
/// Кортеж, содержащий менеджер перетаскивания и сервис перетаскивания.
///
///
/// Этот метод создает все необходимые компоненты для работы перетаскивания в приложении.
/// Возвращаемый сервис можно использовать для создания дополнительных источников и целей.
///
public static (WinUIDragDropManager Manager, IDragDropService Service) CreateCompleteSystem(Window window)
{
var service = DragDropFactory.CreateDragDropService();
var manager = CreateManager(window);
return (manager, service);
}
///
/// Создает систему перетаскивания, оптимизированную для списков и коллекций.
///
///
/// Главное окно приложения.
///
///
/// Менеджер перетаскивания, настроенный для переупорядочивания элементов в списках.
///
///
/// Эта конфигурация устанавливает оптимальные параметры для перетаскивания элементов
/// внутри списков (например, для изменения порядка элементов в ListView или ItemsControl).
///
public static WinUIDragDropManager CreateListReorderSystem(Window window)
{
var manager = CreateManager(window, m =>
{
m.DragVisualOffset = new Core.Geometry.Point(-15, -15);
});
return manager;
}
///
/// Создает систему перетаскивания для файлов и документов.
///
///
/// Главное окно приложения.
///
///
/// Менеджер перетаскивания, настроенный для работы с файлами.
///
///
/// Эта конфигурация устанавливает увеличенный порог перетаскивания и специальные
/// визуальные эффекты, характерные для операций с файлами.
///
public static WinUIDragDropManager CreateFileDragDropSystem(Window window)
{
var manager = CreateManager(window, m =>
{
m.DragVisualOffset = new Core.Geometry.Point(-25, -25);
});
return manager;
}
///
/// Создает систему перетаскивания для графических редакторов и инструментов дизайна.
///
///
/// Главное окно приложения.
///
///
/// Менеджер перетаскивания, настроенный для точного позиционирования.
///
///
/// Эта конфигурация уменьшает порог начала перетаскивания для более точного контроля
/// и устанавливает минималистичную визуализацию.
///
public static WinUIDragDropManager CreateDesignToolSystem(Window window)
{
var manager = CreateManager(window, m =>
{
m.DragVisualOffset = new Core.Geometry.Point(-10, -10);
});
return manager;
}
#endregion
#region Вспомогательные методы
///
/// Настраивает элемент как источник перетаскивания с использованием указанного менеджера.
///
///
/// Менеджер перетаскивания, который будет управлять операцией.
///
///
/// Элемент WinUI, который должен стать источником перетаскивания.
///
///
/// Данные для перетаскивания. Если не указаны, будут использованы DataContext или Tag элемента.
///
///
/// Этот метод является оберткой вокруг ,
/// предоставляя более удобный API.
///
public static void SetupAsDragSource(WinUIDragDropManager manager, Microsoft.UI.Xaml.FrameworkElement element, object dragData = null)
{
if (manager == null)
throw new ArgumentNullException(nameof(manager));
if (element == null)
throw new ArgumentNullException(nameof(element));
manager.MakeDragSource(element, dragData);
}
///
/// Настраивает элемент как цель сброса с использованием указанного менеджера.
///
///
/// Менеджер перетаскивания, который будет управлять операцией.
///
///
/// Элемент WinUI, который должен стать целью сброса.
///
///
/// Этот метод является оберткой вокруг ,
/// предоставляя более удобный API.
///
public static void SetupAsDropTarget(WinUIDragDropManager manager, Microsoft.UI.Xaml.FrameworkElement element)
{
if (manager == null)
throw new ArgumentNullException(nameof(manager));
if (element == null)
throw new ArgumentNullException(nameof(element));
manager.MakeDropTarget(element);
}
///
/// Настраивает контейнер для поддержки переупорядочивания дочерних элементов.
///
///
/// Менеджер перетаскивания.
///
///
/// Контейнер (например, StackPanel или Grid), дочерние элементы которого можно переупорядочивать.
///
///
/// Функция для получения данных перетаскивания из дочернего элемента.
/// Если не указана, используются DataContext дочерних элементов.
///
///
/// Этот метод автоматически настраивает все дочерние элементы контейнера как источники перетаскивания,
/// а сам контейнер — как цель сброса, создавая функциональность переупорядочивания.
///
public static void SetupReorderContainer(
WinUIDragDropManager manager,
Microsoft.UI.Xaml.Controls.Panel container,
Func childSelector = null)
{
if (manager == null)
throw new ArgumentNullException(nameof(manager));
if (container == null)
throw new ArgumentNullException(nameof(container));
// Настраиваем контейнер как цель сброса
manager.MakeDropTarget(container);
// Настраиваем все дочерние элементы как источники перетаскивания
foreach (var child in container.Children)
{
if (child is Microsoft.UI.Xaml.FrameworkElement element)
{
var data = childSelector?.Invoke(element) ?? element.DataContext ?? element.Tag;
manager.MakeDragSource(element, data);
}
}
}
#endregion
#region Методы для работы с XAML
///
/// Настраивает прикрепленные свойства для элемента источника перетаскивания.
///
///
/// Элемент, который должен стать источником перетаскивания.
///
///
/// Данные для перетаскивания.
///
///
/// Этот метод устанавливает attached properties, которые активируют поведение перетаскивания
/// при использовании в XAML. Эквивалентно установке свойств IsDragSource и DragData в XAML.
///
public static void SetupDragSourceInXaml(Microsoft.UI.Xaml.FrameworkElement element, object dragData)
{
if (element == null)
throw new ArgumentNullException(nameof(element));
// Устанавливаем attached properties
element.SetValue(Behaviors.WinUIDragSourceBehavior.IsEnabledProperty, true);
if (dragData != null)
{
element.SetValue(Behaviors.WinUIDragSourceBehavior.DragDataProperty, dragData);
}
}
///
/// Настраивает прикрепленные свойства для элемента цели сброса.
///
///
/// Элемент, который должен стать целью сброса.
///
///
/// Этот метод устанавливает attached properties, которые активируют поведение цели сброса
/// при использовании в XAML. Эквивалентно установке свойства IsDropTarget в XAML.
///
public static void SetupDropTargetInXaml(Microsoft.UI.Xaml.FrameworkElement element)
{
if (element == null)
throw new ArgumentNullException(nameof(element));
element.SetValue(Behaviors.WinUIDropTargetBehavior.IsEnabledProperty, true);
}
#endregion
}