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 }