Files
Lattice/Lattice.UI.DragDrop.WinUI/Extensions/DragDropExtensions.cs

217 lines
6.9 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 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
}