950 lines
43 KiB
C#
950 lines
43 KiB
C#
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 Microsoft.UI.Xaml.Controls;
|
||
using System;
|
||
|
||
namespace Lattice.UI.DragDrop.WinUI.Factories;
|
||
|
||
/// <summary>
|
||
/// Фабрика для создания и настройки компонентов системы перетаскивания WinUI.
|
||
/// Предоставляет удобные методы для быстрой интеграции drag-and-drop функциональности
|
||
/// в приложениях WinUI с поддержкой различных сценариев использования.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// <see cref="WinUIDragDropFactory"/> служит высокоуровневым API для работы с системой
|
||
/// перетаскивания, инкапсулируя сложность инициализации и настройки компонентов.
|
||
/// </para>
|
||
/// <para>
|
||
/// Основные возможности фабрики:
|
||
/// <list type="bullet">
|
||
/// <item>Создание и инициализация менеджера перетаскивания</item>
|
||
/// <item>Генерация поведений для источников и целей перетаскивания</item>
|
||
/// <item>Создание визуальных элементов для обратной связи</item>
|
||
/// <item>Предварительные конфигурации для типовых сценариев</item>
|
||
/// <item>Вспомогательные методы для работы с XAML</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// Фабрика поддерживает два подхода к использованию:
|
||
/// <list type="number">
|
||
/// <item><strong>Императивный подход</strong> - создание компонентов в коде C#</item>
|
||
/// <item><strong>Декларативный подход</strong> - использование attached properties в XAML</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Императивный подход
|
||
/// var manager = WinUIDragDropFactory.CreateManager(window);
|
||
/// manager.MakeDragSource(element, data);
|
||
/// manager.MakeDropTarget(dropArea);
|
||
///
|
||
/// // Декларативный подход (в XAML)
|
||
/// <Border local:DragDropProperties.IsDragSource="True"
|
||
/// local:DragDropProperties.DragData="{Binding Item}" />
|
||
/// <Border local:DragDropProperties.IsDropTarget="True" />
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static class WinUIDragDropFactory
|
||
{
|
||
#region Основные компоненты
|
||
|
||
/// <summary>
|
||
/// Создает и инициализирует менеджер перетаскивания для указанного окна WinUI.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Окно WinUI, для которого создается менеджер перетаскивания.
|
||
/// Не может быть null.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Инициализированный экземпляр <see cref="WinUIDragDropManager"/>.
|
||
/// </returns>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, когда <paramref name="window"/> равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод является основным способом получения менеджера перетаскивания.
|
||
/// Он создает (или возвращает существующий) экземпляр менеджера и инициализирует
|
||
/// его для работы с указанным окном.
|
||
/// </para>
|
||
/// <para>
|
||
/// Метод следует вызывать один раз при запуске приложения, обычно в конструкторе
|
||
/// главного окна или в методе <see cref="Application.OnLaunched"/>.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// public partial class MainWindow : Window
|
||
/// {
|
||
/// public MainWindow()
|
||
/// {
|
||
/// InitializeComponent();
|
||
/// var manager = WinUIDragDropFactory.CreateManager(this);
|
||
/// }
|
||
/// }
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragDropManager CreateManager(Window window)
|
||
{
|
||
if (window == null)
|
||
throw new ArgumentNullException(nameof(window));
|
||
|
||
var manager = WinUIDragDropManager.Instance;
|
||
if (!manager.IsInitialized)
|
||
{
|
||
manager.Initialize(window);
|
||
}
|
||
return manager;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает и инициализирует менеджер перетаскивания с пользовательскими настройками.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Окно WinUI, для которого создается менеджер перетаскивания.
|
||
/// </param>
|
||
/// <param name="configure">
|
||
/// Делегат для настройки параметров менеджера перед инициализацией.
|
||
/// Передает экземпляр <see cref="WinUIDragDropManager"/> для конфигурации.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Инициализированный экземпляр <see cref="WinUIDragDropManager"/>.
|
||
/// </returns>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, когда <paramref name="window"/> равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод позволяет настроить параметры менеджера перед его инициализацией,
|
||
/// что полезно для тонкой настройки поведения системы перетаскивания.
|
||
/// </para>
|
||
/// <para>
|
||
/// Доступные для настройки параметры включают:
|
||
/// <list type="bullet">
|
||
/// <item><see cref="WinUIDragDropManager.DragVisualOffset"/> - смещение визуального элемента</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// var manager = WinUIDragDropFactory.CreateManager(window, m =>
|
||
/// {
|
||
/// m.DragVisualOffset = new Point(-15, -15); // Ближе к курсору
|
||
/// });
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragDropManager CreateManager(Window window, Action<WinUIDragDropManager> configure)
|
||
{
|
||
if (window == null)
|
||
throw new ArgumentNullException(nameof(window));
|
||
|
||
var manager = WinUIDragDropManager.Instance;
|
||
|
||
// Применяем настройки перед инициализацией
|
||
configure?.Invoke(manager);
|
||
|
||
if (!manager.IsInitialized)
|
||
{
|
||
manager.Initialize(window);
|
||
}
|
||
|
||
return manager;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает хост для управления визуальными элементами перетаскивания.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Окно, к которому будет привязан хост.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="WinUIDragDropHost"/>, готовый к использованию.
|
||
/// </returns>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="window"/> равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Хост управляет отображением визуальных элементов во время операций перетаскивания,
|
||
/// включая drag-визуализации (элементы, следующие за курсором) и drop-превью
|
||
/// (подсветка областей сброса).
|
||
/// </para>
|
||
/// <para>
|
||
/// В большинстве случаев хост создается автоматически менеджером перетаскивания.
|
||
/// Этот метод полезен для продвинутых сценариев, когда требуется прямой контроль
|
||
/// над визуальной обратной связью.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// var host = WinUIDragDropFactory.CreateHost(window);
|
||
/// // Настройка кастомной визуализации
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
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)
|
||
|
||
/// <summary>
|
||
/// Создает поведение источника перетаскивания для элемента WinUI.
|
||
/// </summary>
|
||
/// <param name="dragDropService">
|
||
/// Сервис перетаскивания, который будет управлять операциями.
|
||
/// </param>
|
||
/// <param name="host">
|
||
/// Хост для отображения визуальных элементов.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="WinUIDragSourceBehavior"/>, готовый к прикреплению к элементу.
|
||
/// </returns>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если любой из параметров равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Созданное поведение необходимо прикрепить к элементу с помощью метода
|
||
/// <see cref="WinUIDragSourceBehavior.Attach"/>.
|
||
/// </para>
|
||
/// <para>
|
||
/// Этот метод полезен для продвинутых сценариев, когда требуется создавать поведения
|
||
/// вручную, например, при динамическом создании элементов интерфейса.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание поведения вручную
|
||
/// var behavior = WinUIDragDropFactory.CreateDragSourceBehavior(service, host);
|
||
/// behavior.Attach(element, data);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает поведение цели сброса для элемента WinUI.
|
||
/// </summary>
|
||
/// <param name="dragDropService">
|
||
/// Сервис перетаскивания, который будет управлять операциями.
|
||
/// </param>
|
||
/// <param name="host">
|
||
/// Хост для отображения визуальных элементов.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="WinUIDropTargetBehavior"/>, готовый к прикреплению к элементу.
|
||
/// </returns>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если любой из параметров равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Созданное поведение необходимо прикрепить к элементу с помощью метода
|
||
/// <see cref="WinUIDropTargetBehavior.Attach"/>.
|
||
/// </para>
|
||
/// <para>
|
||
/// Поведение можно дополнительно настроить с помощью методов
|
||
/// <see cref="WinUIDropTargetBehavior.AcceptTypes"/> и
|
||
/// <see cref="WinUIDropTargetBehavior.AcceptFormats"/> для фильтрации
|
||
/// принимаемых данных.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание поведения вручную
|
||
/// var behavior = WinUIDragDropFactory.CreateDropTargetBehavior(service, host);
|
||
/// behavior.AcceptTypes(typeof(string), typeof(MyModel));
|
||
/// behavior.Attach(dropArea);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает поведение источника перетаскивания, используя сервисы из менеджера по умолчанию.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="WinUIDragSourceBehavior"/>, готовый к прикреплению к элементу.
|
||
/// </returns>
|
||
/// <exception cref="InvalidOperationException">
|
||
/// Выбрасывается, если менеджер не инициализирован.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод использует <see cref="WinUIDragDropManager.Instance"/> для получения
|
||
/// сервиса перетаскивания и хоста, что упрощает создание поведений в контексте
|
||
/// уже инициализированной системы.
|
||
/// </para>
|
||
/// <para>
|
||
/// Перед использованием убедитесь, что менеджер инициализирован через метод
|
||
/// <see cref="CreateManager"/>.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Инициализация менеджера
|
||
/// WinUIDragDropFactory.CreateManager(window);
|
||
///
|
||
/// // Создание поведения с использованием менеджера
|
||
/// var behavior = WinUIDragDropFactory.CreateDragSourceBehavior();
|
||
/// behavior.Attach(element, data);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragSourceBehavior CreateDragSourceBehavior()
|
||
{
|
||
var manager = WinUIDragDropManager.Instance;
|
||
if (!manager.IsInitialized)
|
||
{
|
||
throw new InvalidOperationException(
|
||
"Менеджер не инициализирован. Вызовите CreateManager перед созданием поведений.");
|
||
}
|
||
|
||
return new WinUIDragSourceBehavior(manager.DragDropService, manager.Host);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает поведение цели сброса, используя сервисы из менеджера по умолчанию.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="WinUIDropTargetBehavior"/>, готовый к прикреплению к элементу.
|
||
/// </returns>
|
||
/// <exception cref="InvalidOperationException">
|
||
/// Выбрасывается, если менеджер не инициализирован.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод использует <see cref="WinUIDragDropManager.Instance"/> для получения
|
||
/// сервиса перетаскивания и хоста, что упрощает создание поведений в контексте
|
||
/// уже инициализированной системы.
|
||
/// </para>
|
||
/// <para>
|
||
/// Поведение можно дополнительно настроить с помощью методов
|
||
/// <see cref="WinUIDropTargetBehavior.AcceptTypes"/> и
|
||
/// <see cref="WinUIDropTargetBehavior.AcceptFormats"/> для фильтрации
|
||
/// принимаемых данных.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Инициализация менеджера
|
||
/// WinUIDragDropFactory.CreateManager(window);
|
||
///
|
||
/// // Создание поведения с использованием менеджера
|
||
/// var behavior = WinUIDragDropFactory.CreateDropTargetBehavior();
|
||
/// behavior.AcceptTypes(typeof(string));
|
||
/// behavior.Attach(dropArea);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDropTargetBehavior CreateDropTargetBehavior()
|
||
{
|
||
var manager = WinUIDragDropManager.Instance;
|
||
if (!manager.IsInitialized)
|
||
{
|
||
throw new InvalidOperationException(
|
||
"Менеджер не инициализирован. Вызовите CreateManager перед созданием поведений.");
|
||
}
|
||
|
||
return new WinUIDropTargetBehavior(manager.DragDropService, manager.Host);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Визуальные элементы
|
||
|
||
/// <summary>
|
||
/// Создает визуальный элемент для отображения во время перетаскивания.
|
||
/// </summary>
|
||
/// <param name="dragData">
|
||
/// Данные, которые будут отображены в визуальном элементе.
|
||
/// Могут быть любого типа, поддерживаемого системой перетаскивания.
|
||
/// </param>
|
||
/// <param name="opacity">
|
||
/// Прозрачность элемента в диапазоне от 0.0 (полностью прозрачный) до 1.0 (полностью непрозрачный).
|
||
/// Значение по умолчанию: 0.8.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="DragAdorner"/>, настроенный для отображения указанных данных.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Созданный элемент можно использовать с методом <see cref="WinUIDragDropHost.ShowDragVisual"/>
|
||
/// для отображения во время операции перетаскивания.
|
||
/// </para>
|
||
/// <para>
|
||
/// Элемент автоматически адаптирует отображение в зависимости от типа данных:
|
||
/// <list type="bullet">
|
||
/// <item>Для строк отображается текстовое представление</item>
|
||
/// <item>Для изображений отображается миниатюра</item>
|
||
/// <item>Для пользовательских объектов используется DataTemplate или ToString()</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание визуального элемента
|
||
/// var adorner = WinUIDragDropFactory.CreateDragAdorner("Текст для перетаскивания");
|
||
///
|
||
/// // Отображение во время перетаскивания
|
||
/// host.ShowDragVisual(adorner, position);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static DragAdorner CreateDragAdorner(object dragData, double opacity = 0.8)
|
||
{
|
||
return new DragAdorner
|
||
{
|
||
DragData = dragData ?? throw new ArgumentNullException(nameof(dragData)),
|
||
Opacity = Math.Clamp(opacity, 0.0, 1.0)
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает элемент предварительного просмотра для области сброса.
|
||
/// </summary>
|
||
/// <param name="color">
|
||
/// Цвет подсветки области. Если не указан, используется системный цвет акцента.
|
||
/// </param>
|
||
/// <param name="thickness">
|
||
/// Толщина границы подсветки в пикселях.
|
||
/// Значение по умолчанию: 2.0.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Экземпляр <see cref="DropPreviewAdorner"/>, готовый к отображению.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот элемент используется для визуального указания области, на которую можно
|
||
/// сбросить данные. Он отображается как подсветка границ целевого элемента с
|
||
/// поддержкой анимации появления и скрытия.
|
||
/// </para>
|
||
/// <para>
|
||
/// Элемент автоматически адаптирует свой внешний вид в зависимости от состояния:
|
||
/// <list type="bullet">
|
||
/// <item><strong>Normal</strong> - стандартное состояние</item>
|
||
/// <item><strong>Highlighted</strong> - подсветка при наведении</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание элемента подсветки
|
||
/// var preview = WinUIDragDropFactory.CreateDropPreviewAdorner(
|
||
/// Colors.Blue, // Цвет
|
||
/// 3.0 // Толщина границы
|
||
/// );
|
||
///
|
||
/// // Отображение подсветки
|
||
/// preview.Show(bounds);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static DropPreviewAdorner CreateDropPreviewAdorner(
|
||
Windows.UI.Color? color = null,
|
||
double thickness = 2.0)
|
||
{
|
||
var adorner = new DropPreviewAdorner
|
||
{
|
||
PreviewThickness = Math.Max(thickness, 0.0)
|
||
};
|
||
|
||
if (color.HasValue)
|
||
{
|
||
adorner.PreviewColor = color.Value;
|
||
}
|
||
|
||
return adorner;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Готовые конфигурации для типовых сценариев
|
||
|
||
/// <summary>
|
||
/// Создает полную систему перетаскивания для WinUI приложения.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Главное окно приложения.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Кортеж, содержащий менеджер перетаскивания и сервис перетаскивания.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод создает все необходимые компоненты для работы перетаскивания в приложении
|
||
/// и возвращает их для дальнейшего использования.
|
||
/// </para>
|
||
/// <para>
|
||
/// Возвращаемый сервис можно использовать для создания дополнительных источников и целей
|
||
/// или для низкоуровневого управления операциями перетаскивания.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание полной системы
|
||
/// var (manager, service) = WinUIDragDropFactory.CreateCompleteSystem(window);
|
||
///
|
||
/// // Использование менеджера для настройки элементов
|
||
/// manager.MakeDragSource(element, data);
|
||
///
|
||
/// // Использование сервиса для расширенного управления
|
||
/// var stats = service.GetStats();
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static (WinUIDragDropManager Manager, IDragDropService Service) CreateCompleteSystem(Window window)
|
||
{
|
||
var manager = CreateManager(window);
|
||
return (manager, manager.DragDropService);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает систему перетаскивания, оптимизированную для переупорядочивания элементов в списках.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Главное окно приложения.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Менеджер перетаскивания, настроенный для переупорядочивания элементов в списках.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Эта конфигурация устанавливает оптимальные параметры для перетаскивания элементов
|
||
/// внутри списков и коллекций, таких как:
|
||
/// <list type="bullet">
|
||
/// <item>Изменение порядка элементов в ListView</item>
|
||
/// <item>Перемещение элементов между ItemsControl</item>
|
||
/// <item>Сортировка элементов в коллекциях</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// Особенности конфигурации:
|
||
/// <list type="bullet">
|
||
/// <item>Уменьшенный порог начала перетаскивания для более быстрого отклика</item>
|
||
/// <item>Смещение визуального элемента для лучшего визуального выравнивания</item>
|
||
/// <item>Оптимизированная визуальная обратная связь</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание системы для переупорядочивания списков
|
||
/// var manager = WinUIDragDropFactory.CreateListReorderSystem(window);
|
||
///
|
||
/// // Настройка ListView для переупорядочивания
|
||
/// foreach (var item in myListView.Items)
|
||
/// {
|
||
/// if (item is FrameworkElement element)
|
||
/// {
|
||
/// manager.MakeDragSource(element, element.DataContext);
|
||
/// }
|
||
/// }
|
||
/// manager.MakeDropTarget(myListView);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragDropManager CreateListReorderSystem(Window window)
|
||
{
|
||
var manager = CreateManager(window, m =>
|
||
{
|
||
// Уменьшенное смещение для лучшего визуального выравнивания в списках
|
||
m.DragVisualOffset = new Core.Geometry.Point(-15, -15);
|
||
});
|
||
|
||
return manager;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает систему перетаскивания для работы с файлами и документами.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Главное окно приложения.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Менеджер перетаскивания, настроенный для работы с файлами.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Эта конфигурация оптимизирована для сценариев работы с файлами:
|
||
/// <list type="bullet">
|
||
/// <item>Перетаскивание файлов из проводника в приложение</item>
|
||
/// <item>Перемещение файлов между элементами интерфейса</item>
|
||
/// <item>Работа с большими объемами данных</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// Особенности конфигурации:
|
||
/// <list type="bullet">
|
||
/// <item>Увеличенный порог перетаскивания для предотвращения случайных операций</item>
|
||
/// <item>Специальные визуальные эффекты, характерные для файловых операций</item>
|
||
/// <item>Оптимизация для работы с внешними источниками данных</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание системы для работы с файлами
|
||
/// var manager = WinUIDragDropFactory.CreateFileDragDropSystem(window);
|
||
///
|
||
/// // Настройка области для приема файлов
|
||
/// manager.MakeDropTarget(fileDropArea);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragDropManager CreateFileDragDropSystem(Window window)
|
||
{
|
||
var manager = CreateManager(window, m =>
|
||
{
|
||
// Увеличенное смещение для файлов (имитация "переноса" файла)
|
||
m.DragVisualOffset = new Core.Geometry.Point(-25, -25);
|
||
});
|
||
|
||
return manager;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает систему перетаскивания для графических редакторов и инструментов дизайна.
|
||
/// </summary>
|
||
/// <param name="window">
|
||
/// Главное окно приложения.
|
||
/// </param>
|
||
/// <returns>
|
||
/// Менеджер перетаскивания, настроенный для точного позиционирования.
|
||
/// </returns>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Эта конфигурация оптимизирована для приложений, требующих высокой точности
|
||
/// позиционирования, таких как:
|
||
/// <list type="bullet">
|
||
/// <item>Графические редакторы (Photoshop, Figma)</item>
|
||
/// <item>Инструменты проектирования интерфейсов</item>
|
||
/// <item>CAD-системы и приложения для 3D-моделирования</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// Особенности конфигурации:
|
||
/// <list type="bullet">
|
||
/// <item>Минимальный порог начала перетаскивания для максимальной точности</item>
|
||
/// <item>Минималистичная визуализация для уменьшения визуального шума</item>
|
||
/// <item>Оптимизация для работы с высокоточными устройствами ввода (графические планшеты)</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Создание системы для графического редактора
|
||
/// var manager = WinUIDragDropFactory.CreateDesignToolSystem(window);
|
||
///
|
||
/// // Настройка инструментов для перетаскивания
|
||
/// manager.MakeDragSource(toolIcon, toolData);
|
||
/// manager.MakeDropTarget(canvas);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static WinUIDragDropManager CreateDesignToolSystem(Window window)
|
||
{
|
||
var manager = CreateManager(window, m =>
|
||
{
|
||
// Минимальное смещение для точного позиционирования
|
||
m.DragVisualOffset = new Core.Geometry.Point(-10, -10);
|
||
});
|
||
|
||
return manager;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Вспомогательные методы
|
||
|
||
/// <summary>
|
||
/// Настраивает элемент как источник перетаскивания с использованием указанного менеджера.
|
||
/// </summary>
|
||
/// <param name="manager">
|
||
/// Менеджер перетаскивания, который будет управлять операцией.
|
||
/// </param>
|
||
/// <param name="element">
|
||
/// Элемент WinUI, который должен стать источником перетаскивания.
|
||
/// </param>
|
||
/// <param name="dragData">
|
||
/// Данные для перетаскивания. Если не указаны, будут использованы DataContext или Tag элемента.
|
||
/// </param>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="manager"/> или <paramref name="element"/> равны null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод является удобной оберткой вокруг <see cref="WinUIDragDropManager.MakeDragSource"/>,
|
||
/// предоставляющей более лаконичный синтаксис.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Использование вспомогательного метода
|
||
/// WinUIDragDropFactory.SetupAsDragSource(manager, myElement, myData);
|
||
///
|
||
/// // Эквивалентно:
|
||
/// manager.MakeDragSource(myElement, myData);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static void SetupAsDragSource(WinUIDragDropManager manager, 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Настраивает элемент как цель сброса с использованием указанного менеджера.
|
||
/// </summary>
|
||
/// <param name="manager">
|
||
/// Менеджер перетаскивания, который будет управлять операцией.
|
||
/// </param>
|
||
/// <param name="element">
|
||
/// Элемент WinUI, который должен стать целью сброса.
|
||
/// </param>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="manager"/> или <paramref name="element"/> равны null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод является удобной оберткой вокруг <see cref="WinUIDragDropManager.MakeDropTarget"/>,
|
||
/// предоставляющей более лаконичный синтаксис.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Использование вспомогательного метода
|
||
/// WinUIDragDropFactory.SetupAsDropTarget(manager, myDropArea);
|
||
///
|
||
/// // Эквивалентно:
|
||
/// manager.MakeDropTarget(myDropArea);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static void SetupAsDropTarget(WinUIDragDropManager manager, FrameworkElement element)
|
||
{
|
||
if (manager == null)
|
||
throw new ArgumentNullException(nameof(manager));
|
||
if (element == null)
|
||
throw new ArgumentNullException(nameof(element));
|
||
|
||
manager.MakeDropTarget(element);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Настраивает контейнер для поддержки переупорядочивания дочерних элементов.
|
||
/// </summary>
|
||
/// <param name="manager">
|
||
/// Менеджер перетаскивания.
|
||
/// </param>
|
||
/// <param name="container">
|
||
/// Контейнер (например, StackPanel, Grid или ItemsControl), дочерние элементы которого можно переупорядочивать.
|
||
/// </param>
|
||
/// <param name="childSelector">
|
||
/// Функция для получения данных перетаскивания из дочернего элемента.
|
||
/// Если не указана, используются DataContext дочерних элементов.
|
||
/// </param>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="manager"/> или <paramref name="container"/> равны null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод автоматически настраивает все дочерние элементы контейнера как источники перетаскивания,
|
||
/// а сам контейнер — как цель сброса, создавая функциональность переупорядочивания элементов.
|
||
/// </para>
|
||
/// <para>
|
||
/// Поддерживаемые типы контейнеров:
|
||
/// <list type="bullet">
|
||
/// <item><see cref="Panel"/> и его производные (StackPanel, Grid, Canvas)</item>
|
||
/// <item><see cref="ItemsControl"/> и его производные (ListView, ListBox)</item>
|
||
/// <item>Любые другие контейнеры с коллекцией дочерних элементов</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Настройка StackPanel для переупорядочивания дочерних элементов
|
||
/// WinUIDragDropFactory.SetupReorderContainer(manager, myStackPanel);
|
||
///
|
||
/// // С кастомным селектором данных
|
||
/// WinUIDragDropFactory.SetupReorderContainer(manager, myListView,
|
||
/// element => ((FrameworkElement)element).DataContext);
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static void SetupReorderContainer(
|
||
WinUIDragDropManager manager,
|
||
FrameworkElement container,
|
||
Func<FrameworkElement, object> childSelector = null)
|
||
{
|
||
if (manager == null)
|
||
throw new ArgumentNullException(nameof(manager));
|
||
if (container == null)
|
||
throw new ArgumentNullException(nameof(container));
|
||
|
||
// Настраиваем контейнер как цель сброса
|
||
manager.MakeDropTarget(container);
|
||
|
||
// Настраиваем дочерние элементы как источники перетаскивания
|
||
if (container is Panel panel)
|
||
{
|
||
SetupPanelChildren(manager, panel, childSelector);
|
||
}
|
||
else if (container is ItemsControl itemsControl)
|
||
{
|
||
SetupItemsControlChildren(manager, itemsControl, childSelector);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Настраивает дочерние элементы Panel как источники перетаскивания.
|
||
/// </summary>
|
||
private static void SetupPanelChildren(
|
||
WinUIDragDropManager manager,
|
||
Panel panel,
|
||
Func<FrameworkElement, object> childSelector)
|
||
{
|
||
foreach (var child in panel.Children)
|
||
{
|
||
if (child is FrameworkElement element)
|
||
{
|
||
var data = childSelector?.Invoke(element) ?? element.DataContext ?? element.Tag;
|
||
manager.MakeDragSource(element, data);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Настраивает элементы ItemsControl как источники перетаскивания.
|
||
/// </summary>
|
||
private static void SetupItemsControlChildren(
|
||
WinUIDragDropManager manager,
|
||
ItemsControl itemsControl,
|
||
Func<FrameworkElement, object> childSelector)
|
||
{
|
||
// Для ItemsControl нам нужно работать с ItemContainerGenerator
|
||
// В реальной реализации здесь должна быть более сложная логика
|
||
// для обработки виртуализации и динамических элементов
|
||
|
||
foreach (var item in itemsControl.Items)
|
||
{
|
||
if (item is FrameworkElement element)
|
||
{
|
||
var data = childSelector?.Invoke(element) ?? element.DataContext ?? element.Tag;
|
||
manager.MakeDragSource(element, data);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Методы для работы с XAML
|
||
|
||
/// <summary>
|
||
/// Настраивает attached properties для элемента источника перетаскивания.
|
||
/// </summary>
|
||
/// <param name="element">
|
||
/// Элемент, который должен стать источником перетаскивания.
|
||
/// </param>
|
||
/// <param name="dragData">
|
||
/// Данные для перетаскивания.
|
||
/// </param>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="element"/> равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод устанавливает attached properties, которые активируют поведение перетаскивания
|
||
/// при использовании в XAML. Эквивалентно установке свойств IsDragSource и DragData в XAML.
|
||
/// </para>
|
||
/// <para>
|
||
/// Метод полезен для динамической настройки элементов в коде C# при сохранении
|
||
/// декларативного стиля программирования.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Настройка элемента в коде C#
|
||
/// WinUIDragDropFactory.SetupDragSourceInXaml(myElement, myData);
|
||
///
|
||
/// // Эквивалентно в XAML:
|
||
/// <Border local:DragDropProperties.IsDragSource="True"
|
||
/// local:DragDropProperties.DragData="{Binding MyData}" />
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static void SetupDragSourceInXaml(FrameworkElement element, object dragData)
|
||
{
|
||
if (element == null)
|
||
throw new ArgumentNullException(nameof(element));
|
||
|
||
// Устанавливаем attached properties
|
||
element.SetValue(DragDropProperties.IsDragSourceProperty, true);
|
||
if (dragData != null)
|
||
{
|
||
element.SetValue(DragDropProperties.DragDataProperty, dragData);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Настраивает attached properties для элемента цели сброса.
|
||
/// </summary>
|
||
/// <param name="element">
|
||
/// Элемент, который должен стать целью сброса.
|
||
/// </param>
|
||
/// <exception cref="ArgumentNullException">
|
||
/// Выбрасывается, если <paramref name="element"/> равен null.
|
||
/// </exception>
|
||
/// <remarks>
|
||
/// <para>
|
||
/// Этот метод устанавливает attached properties, которые активируют поведение цели сброса
|
||
/// при использовании в XAML. Эквивалентно установке свойства IsDropTarget в XAML.
|
||
/// </para>
|
||
/// <para>
|
||
/// Метод полезен для динамической настройки элементов в коде C# при сохранении
|
||
/// декларативного стиля программирования.
|
||
/// </para>
|
||
/// <example>
|
||
/// <code>
|
||
/// // Настройка элемента в коде C#
|
||
/// WinUIDragDropFactory.SetupDropTargetInXaml(myDropArea);
|
||
///
|
||
/// // Эквивалентно в XAML:
|
||
/// <Border local:DragDropProperties.IsDropTarget="True" />
|
||
/// </code>
|
||
/// </example>
|
||
/// </remarks>
|
||
public static void SetupDropTargetInXaml(FrameworkElement element)
|
||
{
|
||
if (element == null)
|
||
throw new ArgumentNullException(nameof(element));
|
||
|
||
element.SetValue(DragDropProperties.IsDropTargetProperty, true);
|
||
}
|
||
|
||
#endregion
|
||
} |