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;
///
/// Методы расширения для настройки перетаскивания в WinUI.
///
public static class DragDropExtensions
{
#region Drag Source Extensions
///
/// Делает элемент источником перетаскивания с указанными данными.
///
public static void MakeDragSource(this FrameworkElement element, object dragData)
{
Behaviors.WinUIDragSourceBehavior.SetDragData(element, dragData);
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, true);
}
///
/// Делает элемент источником перетаскивания с фабрикой данных.
///
public static void MakeDragSource(this FrameworkElement element, Func dataFactory)
{
element.MakeDragSource(dataFactory());
}
///
/// Удаляет возможность перетаскивания с элемента.
///
public static void RemoveDragSource(this FrameworkElement element)
{
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, false);
}
///
/// Проверяет, является ли элемент источником перетаскивания.
///
public static bool IsDragSource(this FrameworkElement element)
{
return Behaviors.WinUIDragSourceBehavior.GetIsEnabled(element);
}
///
/// Получает данные перетаскивания из элемента.
///
public static object? GetDragData(this FrameworkElement element)
{
return Behaviors.WinUIDragSourceBehavior.GetDragData(element);
}
#endregion
#region Drop Target Extensions
///
/// Делает элемент целью сброса.
///
public static void MakeDropTarget(this FrameworkElement element)
{
// Включаем AllowDrop для WinUI
element.AllowDrop = true;
element.SetValue(IsDropTargetProperty, true);
}
///
/// Делает элемент целью сброса с фильтром типов данных.
///
public static void MakeDropTarget(this FrameworkElement element, params Type[] acceptedTypes)
{
element.SetValue(AcceptsDataTypesProperty, acceptedTypes);
element.MakeDropTarget();
}
///
/// Удаляет возможность сброса с элемента.
///
public static void RemoveDropTarget(this FrameworkElement element)
{
element.AllowDrop = false;
element.SetValue(IsDropTargetProperty, false);
}
///
/// Проверяет, является ли элемент целью сброса.
///
public static bool IsDropTarget(this FrameworkElement element)
{
return (bool)element.GetValue(IsDropTargetProperty);
}
///
/// Attached property для отметки цели сброса.
///
public static readonly DependencyProperty IsDropTargetProperty =
DependencyProperty.RegisterAttached(
"IsDropTarget",
typeof(bool),
typeof(DragDropExtensions),
new PropertyMetadata(false));
///
/// Attached property для фильтра типов данных.
///
public static readonly DependencyProperty AcceptsDataTypesProperty =
DependencyProperty.RegisterAttached(
"AcceptsDataTypes",
typeof(Type[]),
typeof(DragDropExtensions),
new PropertyMetadata(null));
///
/// Получает фильтр типов данных.
///
public static Type[]? GetAcceptsDataTypes(this FrameworkElement element)
{
return (Type[]?)element.GetValue(AcceptsDataTypesProperty);
}
#endregion
#region Style Extensions
///
/// Применяет стиль перетаскивания к элементу.
///
public static void ApplyDragStyle(this Control control)
{
var style = Application.Current.Resources["DragEnabledStyle"] as Style;
if (style != null)
{
control.Style = style;
}
else
{
// Fallback стиль
var brush = Application.Current.Resources["SystemControlBackgroundAccentBrush"] as SolidColorBrush;
if (brush != null)
{
control.Background = brush;
}
}
}
///
/// Переключает визуальное состояние элемента для перетаскивания.
///
public static void SetDragVisualState(this Control control, string stateName, bool useTransitions = true)
{
try
{
VisualStateManager.GoToState(control, stateName, useTransitions);
}
catch
{
// Fallback для элементов без визуальных состояний
switch (stateName)
{
case "Dragging":
control.Opacity = 0.7;
break;
case "DragOver":
control.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(50, 0, 120, 215));
break;
case "Normal":
control.ClearValue(Control.OpacityProperty);
control.ClearValue(Control.BackgroundProperty);
break;
}
}
}
#endregion
#region Advanced Configuration
///
/// Создает контейнер с поддержкой перетаскивания для элементов.
///
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(FrameworkElement));
}
return container;
}
///
/// Делает все дочерние элементы перетаскиваемыми.
///
public static void MakeChildrenDraggable(this Panel container, Func dataSelector)
{
foreach (var child in container.Children.OfType())
{
var data = dataSelector(child);
child.MakeDragSource(data);
}
}
#endregion
}