DragAndDrop core
This commit is contained in:
327
Lattice.UI.DragDrop.WinUI/Extensions/DragDropExtensions.cs
Normal file
327
Lattice.UI.DragDrop.WinUI/Extensions/DragDropExtensions.cs
Normal file
@@ -0,0 +1,327 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user