Files
Lattice/Lattice.UI.DragDrop.WinUI/Extensions/DragDropExtensions.cs
2026-01-18 16:33:35 +03:00

327 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using System.Linq;
namespace Lattice.UI.DragDrop.WinUI.Extensions;
/// <summary>
/// Методы расширения для настройки перетаскивания в WinUI.
/// </summary>
public static class DragDropExtensions
{
#region Drag Source Extensions
/// <summary>
/// Делает элемент источником перетаскивания с указанными данными.
/// </summary>
public static void MakeDragSource(this UIElement element, object dragData)
{
Behaviors.WinUIDragSourceBehavior.SetDragData(element, dragData);
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, true);
}
/// <summary>
/// Делает элемент источником перетаскивания с фабрикой данных.
/// </summary>
public static void MakeDragSource(this UIElement element, Func<object> dataFactory)
{
element.MakeDragSource(dataFactory());
}
/// <summary>
/// Делает элемент источником перетаскивания с настраиваемыми параметрами.
/// </summary>
public static void MakeDragSource(this UIElement element,
object dragData,
Core.DragDrop.Enums.DragDropEffects allowedEffects,
Func<bool>? canDrag = null)
{
element.MakeDragSource(dragData);
element.SetAllowedEffects(allowedEffects);
if (canDrag != null)
{
// Можно добавить кастомную логику проверки
}
}
/// <summary>
/// Удаляет возможность перетаскивания с элемента.
/// </summary>
public static void RemoveDragSource(this UIElement element)
{
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, false);
}
/// <summary>
/// Устанавливает разрешенные эффекты перетаскивания для элемента.
/// </summary>
public static void SetAllowedEffects(this UIElement element, Core.DragDrop.Enums.DragDropEffects effects)
{
Behaviors.WinUIDragSourceBehavior.SetAllowedEffects(element, effects);
}
/// <summary>
/// Устанавливает смещение для визуального элемента перетаскивания.
/// </summary>
public static void SetDragVisualOffset(this UIElement element, double offsetX, double offsetY)
{
if (element is FrameworkElement frameworkElement)
{
frameworkElement.Tag = new Windows.Foundation.Point(offsetX, offsetY);
}
}
#endregion
#region Drop Target Extensions
/// <summary>
/// Делает элемент целью сброса.
/// </summary>
public static void MakeDropTarget(this UIElement element)
{
Behaviors.WinUIDropTargetBehavior.SetIsEnabled(element, true);
}
/// <summary>
/// Делает элемент целью сброса с фильтром типов данных.
/// </summary>
public static void MakeDropTarget(this UIElement element, params Type[] acceptedTypes)
{
Behaviors.WinUIDropTargetBehavior.SetAcceptsDataTypes(element, acceptedTypes);
Behaviors.WinUIDropTargetBehavior.SetIsEnabled(element, true);
}
/// <summary>
/// Делает элемент целью сброса с обработчиком.
/// </summary>
public static void MakeDropTarget(this UIElement element, Core.DragDrop.Abstractions.IDropTarget handler)
{
Behaviors.WinUIDropTargetBehavior.SetDropHandler(element, handler);
Behaviors.WinUIDropTargetBehavior.SetIsEnabled(element, true);
}
/// <summary>
/// Делает элемент целью сброса с полной настройкой.
/// </summary>
public static void MakeDropTarget(this UIElement element,
Type[] acceptedTypes,
Core.DragDrop.Abstractions.IDropTarget? handler = null,
bool showVisualFeedback = true,
Style? feedbackStyle = null)
{
if (acceptedTypes != null && acceptedTypes.Length > 0)
{
Behaviors.WinUIDropTargetBehavior.SetAcceptsDataTypes(element, acceptedTypes);
}
if (handler != null)
{
Behaviors.WinUIDropTargetBehavior.SetDropHandler(element, handler);
}
Behaviors.WinUIDropTargetBehavior.SetShowVisualFeedback(element, showVisualFeedback);
if (feedbackStyle != null)
{
Behaviors.WinUIDropTargetBehavior.SetFeedbackStyle(element, feedbackStyle);
}
Behaviors.WinUIDropTargetBehavior.SetIsEnabled(element, true);
}
/// <summary>
/// Удаляет возможность сброса с элемента.
/// </summary>
public static void RemoveDropTarget(this UIElement element)
{
Behaviors.WinUIDropTargetBehavior.SetIsEnabled(element, false);
}
/// <summary>
/// Устанавливает стиль визуальной обратной связи для цели сброса.
/// </summary>
public static void SetDropFeedbackStyle(this UIElement element, Style style)
{
Behaviors.WinUIDropTargetBehavior.SetFeedbackStyle(element, style);
}
/// <summary>
/// Включает или выключает визуальную обратную связь при сбросе.
/// </summary>
public static void SetDropVisualFeedback(this UIElement element, bool enabled)
{
Behaviors.WinUIDropTargetBehavior.SetShowVisualFeedback(element, enabled);
}
#endregion
#region Style Extensions
/// <summary>
/// Применяет стиль перетаскивания к элементу.
/// </summary>
public static void ApplyDragStyle(this Control control)
{
var style = Application.Current.Resources["DragEnabledStyle"] as Style;
if (style != null)
{
control.Style = style;
}
}
/// <summary>
/// Применяет стиль цели сброса к элементу.
/// </summary>
public static void ApplyDropTargetStyle(this Control control)
{
var style = Application.Current.Resources["DropTargetStyle"] as Style;
if (style != null)
{
control.Style = style;
}
}
/// <summary>
/// Включает визуальную обратную связь для элемента при перетаскивании.
/// </summary>
public static void EnableDragVisualFeedback(this Control control)
{
control.Loaded += (sender, e) =>
{
// Убеждаемся, что у элемента есть визуальные состояния
EnsureVisualStates(control);
};
}
/// <summary>
/// Переключает визуальное состояние элемента для перетаскивания.
/// </summary>
public static void SetDragVisualState(this Control control, string stateName, bool useTransitions = true)
{
try
{
VisualStateManager.GoToState(control, stateName, useTransitions);
}
catch
{
// Если состояние не найдено, используем альтернативные методы
switch (stateName)
{
case "Dragging":
control.Opacity = 0.7;
control.RenderTransform = new ScaleTransform { ScaleX = 0.95, ScaleY = 0.95 };
break;
case "DragOver":
control.Background = Application.Current.Resources["DragOverBackgroundBrush"] as Brush;
control.BorderBrush = Application.Current.Resources["DragOverBorderBrush"] as Brush;
break;
case "Normal":
control.ClearValue(Control.OpacityProperty);
control.ClearValue(Control.RenderTransformProperty);
control.ClearValue(Control.BackgroundProperty);
control.ClearValue(Control.BorderBrushProperty);
break;
}
}
}
#endregion
#region Advanced Configuration
/// <summary>
/// Настраивает элемент для работы с сервисом перетаскивания.
/// </summary>
public static void ConfigureForDragDropService(this UIElement element,
Core.DragDrop.Services.IDragDropService service,
string? dropTargetGroup = null)
{
// Этот метод позволяет интегрировать элемент с централизованным сервисом
// В реальной реализации нужно регистрировать элемент в сервисе
}
/// <summary>
/// Создает контейнер с поддержкой перетаскивания для элементов.
/// </summary>
public static Panel CreateDragDropContainer(
Orientation orientation = Orientation.Vertical,
double spacing = 8,
bool enableReordering = true)
{
var container = new StackPanel
{
Orientation = orientation,
Spacing = spacing
};
if (enableReordering)
{
// Настраиваем контейнер для переупорядочивания элементов
container.MakeDropTarget(typeof(UIElement));
}
return container;
}
/// <summary>
/// Делает все дочерние элементы перетаскиваемыми.
/// </summary>
public static void MakeChildrenDraggable(this Panel container, Func<UIElement, object> dataSelector)
{
foreach (var child in container.Children.OfType<UIElement>())
{
var data = dataSelector(child);
child.MakeDragSource(data);
}
}
#endregion
#region Utility Methods
/// <summary>
/// Проверяет, является ли элемент источником перетаскивания.
/// </summary>
public static bool IsDragSource(this UIElement element)
{
return Behaviors.WinUIDragSourceBehavior.GetIsEnabled(element);
}
/// <summary>
/// Проверяет, является ли элемент целью сброса.
/// </summary>
public static bool IsDropTarget(this UIElement element)
{
return Behaviors.WinUIDropTargetBehavior.GetIsEnabled(element);
}
/// <summary>
/// Получает данные перетаскивания из элемента.
/// </summary>
public static object? GetDragData(this UIElement element)
{
return Behaviors.WinUIDragSourceBehavior.GetDragData(element);
}
#endregion
#region Helper Methods
private static void EnsureVisualStates(Control control)
{
// В WinUI 3 визуальные состояния должны быть определены в стиле элемента
// Этот метод проверяет, что у элемента есть базовые визуальные состояния
if (control.Template == null && control.Style == null)
{
// Применяем стандартный стиль, если у элемента нет своего
control.ApplyDragStyle();
}
}
#endregion
}