217 lines
6.9 KiB
C#
217 lines
6.9 KiB
C#
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 FrameworkElement element, object dragData)
|
||
{
|
||
Behaviors.WinUIDragSourceBehavior.SetDragData(element, dragData);
|
||
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Делает элемент источником перетаскивания с фабрикой данных.
|
||
/// </summary>
|
||
public static void MakeDragSource(this FrameworkElement element, Func<object> dataFactory)
|
||
{
|
||
element.MakeDragSource(dataFactory());
|
||
}
|
||
|
||
/// <summary>
|
||
/// Удаляет возможность перетаскивания с элемента.
|
||
/// </summary>
|
||
public static void RemoveDragSource(this FrameworkElement element)
|
||
{
|
||
Behaviors.WinUIDragSourceBehavior.SetIsEnabled(element, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверяет, является ли элемент источником перетаскивания.
|
||
/// </summary>
|
||
public static bool IsDragSource(this FrameworkElement element)
|
||
{
|
||
return Behaviors.WinUIDragSourceBehavior.GetIsEnabled(element);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Получает данные перетаскивания из элемента.
|
||
/// </summary>
|
||
public static object? GetDragData(this FrameworkElement element)
|
||
{
|
||
return Behaviors.WinUIDragSourceBehavior.GetDragData(element);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Drop Target Extensions
|
||
|
||
/// <summary>
|
||
/// Делает элемент целью сброса.
|
||
/// </summary>
|
||
public static void MakeDropTarget(this FrameworkElement element)
|
||
{
|
||
// Включаем AllowDrop для WinUI
|
||
element.AllowDrop = true;
|
||
element.SetValue(IsDropTargetProperty, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Делает элемент целью сброса с фильтром типов данных.
|
||
/// </summary>
|
||
public static void MakeDropTarget(this FrameworkElement element, params Type[] acceptedTypes)
|
||
{
|
||
element.SetValue(AcceptsDataTypesProperty, acceptedTypes);
|
||
element.MakeDropTarget();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Удаляет возможность сброса с элемента.
|
||
/// </summary>
|
||
public static void RemoveDropTarget(this FrameworkElement element)
|
||
{
|
||
element.AllowDrop = false;
|
||
element.SetValue(IsDropTargetProperty, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверяет, является ли элемент целью сброса.
|
||
/// </summary>
|
||
public static bool IsDropTarget(this FrameworkElement element)
|
||
{
|
||
return (bool)element.GetValue(IsDropTargetProperty);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Attached property для отметки цели сброса.
|
||
/// </summary>
|
||
public static readonly DependencyProperty IsDropTargetProperty =
|
||
DependencyProperty.RegisterAttached(
|
||
"IsDropTarget",
|
||
typeof(bool),
|
||
typeof(DragDropExtensions),
|
||
new PropertyMetadata(false));
|
||
|
||
/// <summary>
|
||
/// Attached property для фильтра типов данных.
|
||
/// </summary>
|
||
public static readonly DependencyProperty AcceptsDataTypesProperty =
|
||
DependencyProperty.RegisterAttached(
|
||
"AcceptsDataTypes",
|
||
typeof(Type[]),
|
||
typeof(DragDropExtensions),
|
||
new PropertyMetadata(null));
|
||
|
||
/// <summary>
|
||
/// Получает фильтр типов данных.
|
||
/// </summary>
|
||
public static Type[]? GetAcceptsDataTypes(this FrameworkElement element)
|
||
{
|
||
return (Type[]?)element.GetValue(AcceptsDataTypesProperty);
|
||
}
|
||
|
||
#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;
|
||
}
|
||
else
|
||
{
|
||
// Fallback стиль
|
||
var brush = Application.Current.Resources["SystemControlBackgroundAccentBrush"] as SolidColorBrush;
|
||
if (brush != null)
|
||
{
|
||
control.Background = brush;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Переключает визуальное состояние элемента для перетаскивания.
|
||
/// </summary>
|
||
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
|
||
|
||
/// <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(FrameworkElement));
|
||
}
|
||
|
||
return container;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Делает все дочерние элементы перетаскиваемыми.
|
||
/// </summary>
|
||
public static void MakeChildrenDraggable(this Panel container, Func<FrameworkElement, object> dataSelector)
|
||
{
|
||
foreach (var child in container.Children.OfType<FrameworkElement>())
|
||
{
|
||
var data = dataSelector(child);
|
||
child.MakeDragSource(data);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
} |