Lattice.UI.DragDrop.WinUI
Полнофункциональная реализация системы перетаскивания для WinUI 3 в составе Lattice UI Framework.
🎉 Демо
Перетаскивание элементов между контейнерами и переупорядочивание списка
📦 Особенности
✅ Готовое решение для WinUI 3 - работает из коробки
✅ Attached Behaviors - легко подключается к любым UIElement
✅ Визуальная обратная связь - анимации и подсветка
✅ Переупорядочивание элементов - drag-and-drop в списках
✅ Кастомизация стилей - полный контроль над внешним видом
✅ Поддержка сложных сценариев - вложенные элементы, зоны сброса
✅ Производительность - оптимизировано для плавной работы
🚀 Быстрый старт
1. Установка
Добавьте пакет через NuGet:
Install-Package Lattice.UI.DragDrop.WinUI
Или через Package Manager:
<PackageReference Include="Lattice.UI.DragDrop.WinUI" Version="1.0.0" />
2. Инициализация в приложении
using Lattice.UI.DragDrop.WinUI.Extensions;
using Lattice.UI.DragDrop.WinUI.Helpers;
public MainWindow()
{
InitializeComponent();
// Инициализация ресурсов
ResourceHelper.InitializeDragDropResources();
// Настройка примеров перетаскивания
SetupDragDropExamples();
}
private void SetupDragDropExamples()
{
// Пример 1: Перетаскивание текста
var textBlock = new TextBlock { Text = "Перетащи меня" };
textBlock.MakeDragSource("Пример данных");
// Пример 2: Цель сброса
var border = new Border { Background = new SolidColorBrush(Colors.LightGray) };
border.MakeDropTarget(typeof(string));
// Пример 3: Стилизация
var button = new Button { Content = "Кнопка" };
button.ApplyDragStyle();
button.EnableDragVisualFeedback();
}
🎨 Использование
Базовое перетаскивание
// Создаем перетаскиваемый элемент
var dragSource = new Border
{
Background = new SolidColorBrush(Colors.LightBlue),
Child = new TextBlock { Text = "Drag me" }
};
// Делаем элемент перетаскиваемым
dragSource.MakeDragSource(dragSource); // Можно передать любые данные
// Создаем цель сброса
var dropTarget = new Border
{
Background = new SolidColorBrush(Colors.LightGreen)
};
// Делаем элемент целью сброса
dropTarget.MakeDropTarget(typeof(Border));
Переупорядочивание элементов в списке
// Создаем контейнер с поддержкой переупорядочивания
var reorderContainer = new StackPanel();
reorderContainer.MakeDropTarget(typeof(UIElement));
// Добавляем перетаскиваемые элементы
for (int i = 0; i < 5; i++)
{
var item = new Border
{
Background = new SolidColorBrush(Colors.White),
BorderBrush = new SolidColorBrush(Colors.Gray),
BorderThickness = new Thickness(1),
Margin = new Thickness(0, 0, 0, 5),
Child = new TextBlock { Text = $"Item {i + 1}" }
};
item.MakeDragSource(item);
reorderContainer.Children.Add(item);
}
Кастомизация визуальной обратной связи
// Создаем кастомный стиль
var customStyle = new Style(typeof(Control));
customStyle.Setters.Add(new Setter(Control.BackgroundProperty,
new SolidColorBrush(Colors.Yellow)));
customStyle.Setters.Add(new Setter(Control.BorderBrushProperty,
new SolidColorBrush(Colors.Red)));
// Применяем стиль к элементу
var element = new Button { Content = "Custom Style" };
element.SetDropFeedbackStyle(customStyle);
element.MakeDragSource("data");
📁 Структура API
Behaviors (Поведения)
| Класс | Описание |
|---|---|
WinUIDragSourceBehavior |
Прикрепляемое поведение для источников |
WinUIDropTargetBehavior |
Прикрепляемое поведение для целей |
Controls (Контролы)
| Контрол | Назначение |
|---|---|
DragAdorner |
Визуальное представление перетаскивания |
DropPreviewAdorner |
Предпросмотр области сброса |
DragDropOverlay |
Оверлей для визуальных элементов |
Services (Сервисы)
| Сервис | Назначение |
|---|---|
WinUIDragVisualProvider |
Создание визуальных элементов |
DragDropConfigurationService |
Централизованная настройка |
Extensions (Расширения)
// Основные методы расширения
element.MakeDragSource(data); // Сделать перетаскиваемым
element.MakeDropTarget(types); // Сделать целью сброса
control.ApplyDragStyle(); // Применить стиль перетаскивания
control.SetDragVisualState("Dragging"); // Установить визуальное состояние
🎯 Примеры использования
Пример 1: Файловый менеджер
// Перетаскивание файлов
var fileItem = new ListViewItem { Content = "Document.pdf" };
fileItem.MakeDragSource(new FileData { Path = "C:\\Files\\Document.pdf" });
// Папка - цель сброса
var folderItem = new ListViewItem { Content = "Downloads" };
folderItem.MakeDropTarget(typeof(FileData));
folderItem.SetDropHandler(new FileDropHandler());
Пример 2: Конструктор UI
// Панель инструментов
var toolbox = new StackPanel();
toolbox.MakeChildrenDraggable(element => new ControlTemplate
{
Type = element.GetType(),
Name = element.Name
});
// Область дизайна
var designArea = new Canvas();
designArea.MakeDropTarget(typeof(ControlTemplate));
// Обработчик сброса
designArea.Drop += (sender, e) =>
{
var template = e.DataView.GetData<ControlTemplate>();
var control = Activator.CreateInstance(template.Type);
Canvas.SetLeft(control, e.GetPosition(designArea).X);
Canvas.SetTop(control, e.GetPosition(designArea).Y);
designArea.Children.Add(control);
};
Пример 3: Календарь с событиями
// Событие календаря
var calendarEvent = new Border
{
Background = new SolidColorBrush(Colors.CornflowerBlue),
Child = new TextBlock { Text = "Meeting at 10:00" }
};
calendarEvent.MakeDragSource(new CalendarEvent
{
Id = 1,
Title = "Meeting",
StartTime = DateTime.Now
});
// Ячейка календаря
var timeSlot = new Border
{
Background = new SolidColorBrush(Colors.White),
BorderBrush = new SolidColorBrush(Colors.LightGray)
};
timeSlot.MakeDropTarget(typeof(CalendarEvent));
🎨 Темы и стилизация
Встроенные стили
Проект включает готовые стили в папке Themes/:
DragAdorner.xaml- стиль для визуального элемента перетаскиванияDropPreviewAdorner.xaml- стиль для предпросмотра сбросаDragDropStyles.xaml- общие стили для элементов
Кастомизация через ресурсы
<!-- App.xaml или Generic.xaml -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///Lattice.UI.DragDrop.WinUI/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Переопределение стилей -->
<Style x:Key="CustomDragAdornerStyle" TargetType="dragDrop:DragAdorner">
<Setter Property="Background" Value="Red" />
<Setter Property="Opacity" Value="0.9" />
</Style>
</ResourceDictionary>
Визуальные состояния
Элементы поддерживают следующие визуальные состояния:
Normal- обычное состояниеDragging- элемент перетаскиваетсяDragOver- над элементом перетаскивают объект
// Переключение состояний
control.SetDragVisualState("Dragging", true); // С анимацией
control.SetDragVisualState("Normal", false); // Без анимации
🔧 Интеграция с Docking System
Система идеально интегрируется с Lattice Docking:
using Lattice.UI.DragDrop.WinUI.Extensions;
using Lattice.UI.Docking.WinUI;
public class DockPane : ContentControl
{
public DockPane()
{
// Делаем панель перетаскиваемой
this.MakeDragSource(new DockPaneDragData
{
Pane = this,
ContentType = Content?.GetType(),
Title = Title
});
// Устанавливаем визуальную обратную связь
this.ApplyDragStyle();
this.EnableDragVisualFeedback();
}
}
public class DockArea : ContentControl
{
public DockArea()
{
// Область докинга принимает панели
this.MakeDropTarget(typeof(DockPaneDragData));
// Кастомный обработчик
this.SetDropHandler(new DockDropHandler());
}
}
📊 Производительность
Оптимизации
- Минимальные перерисовки - обновление только при необходимости
- Кэширование визуальных элементов - повторное использование
- Эффективные алгоритмы поиска - быстрый поиск целей сброса
- Асинхронная обработка - не блокирует UI поток
Рекомендации
// ✅ Правильно
element.MakeDragSource(data);
// ❌ Избегать
element.PointerPressed += (s, e) => { /* сложная логика */ };
element.PointerMoved += (s, e) => { /* частые обновления */ };
🧪 Тестирование
Модульные тесты
[TestClass]
public class DragDropTests
{
[TestMethod]
public void MakeDragSource_EnablesDragging()
{
var element = new Border();
element.MakeDragSource("test");
Assert.IsTrue(element.IsDragSource());
}
[TestMethod]
public void MakeDropTarget_AcceptsCorrectTypes()
{
var element = new Border();
element.MakeDropTarget(typeof(string), typeof(int));
Assert.IsTrue(element.IsDropTarget());
}
}
UI тесты
[TestClass]
public class DragDropUITests
{
[UITestMethod]
public async Task DragAndDrop_BetweenElements()
{
await UITestHelper.Run(async window =>
{
var source = new Border { Background = new SolidColorBrush(Colors.Blue) };
var target = new Border { Background = new SolidColorBrush(Colors.Green) };
source.MakeDragSource("data");
target.MakeDropTarget(typeof(string));
// Симуляция перетаскивания
await SimulateDrag(source, target);
// Проверка результатов
Assert.IsTrue(dropOccurred);
});
}
}
🔍 Отладка
Включение логов
// Включение подробного логирования
#if DEBUG
DragDropDebugger.EnableLogging = true;
DragDropDebugger.LogLevel = LogLevel.Verbose;
#endif
Визуальные подсказки
// Показать границы целей сброса
DebugDropTargets.ShowBounds = true;
// Показать траекторию перетаскивания
DebugDragTrail.Enabled = true;
DebugDragTrail.Color = Colors.Red;
📈 Производительность в production
Мониторинг
// Сбор метрик
var metrics = DragDropPerformanceCollector.Collect();
Console.WriteLine($"Drag operations: {metrics.DragCount}");
Console.WriteLine($"Average drag time: {metrics.AverageDragTimeMs}ms");
Console.WriteLine($"Drop success rate: {metrics.DropSuccessRate:P}");
Оптимизация для больших списков
// Виртуализация для списков
var virtualizingList = new ListView
{
ItemsSource = largeCollection,
VirtualizingStackPanel.VirtualizationMode = VirtualizationMode.Recycling
};
// Оптимизация перетаскивания
virtualizingList.MakeDropTarget(typeof(DataItem));
virtualizingList.SetDragDropOptimization(true);
🤝 Интеграция с другими компонентами Lattice
Toolbox
toolboxItem.MakeDragSource(new ToolboxItem
{
Type = typeof(Button),
Icon = "🔘"
});
Property Grid
propertyItem.MakeDragSource(new PropertyValue
{
Name = "Background",
Value = Colors.Blue
});
Layout System
layoutPanel.MakeDropTarget(typeof(UIElement));
layoutPanel.SetDropPositionHandler((element, position) =>
{
return CalculateDropZone(position);
});
📚 Дополнительные ресурсы
Документация
Видео туториалы
- Быстрый старт - 15 минут
- Продвинутые техники - 45 минут
- Интеграция с Docking - 30 минут
Сообщество
- GitHub Discussions - вопросы и обсуждения
- Discord - живое общение
- Stack Overflow - технические вопросы
🐛 Отчет об ошибках
Нашли ошибку? Создайте issue с подробным описанием:
- Шаги для воспроизведения
- Ожидаемое поведение
- Фактическое поведение
- Скриншоты или видео
- Версии: Windows, WinUI, Lattice
🚀 Roadmap
Версия 1.1 (Q2 2024)
- Поддержка touch-жестов
- Анимации с физикой
- Расширенная визуализация
Версия 1.2 (Q3 2024)
- Интеграция с Windows Shell
- Поддержка виртуальных данных
- Улучшенная доступность
Версия 2.0 (Q4 2024)
- Кроссплатформенная поддержка (Uno Platform)
- WebAssembly поддержка
- Расширенный набор контролов
📄 Лицензия
MIT License. Подробности в файле LICENSE.
👥 Авторы
- Команда Lattice Framework - @lattice-framework
- Главный разработчик - Ваше имя
🙏 Благодарности
Спасибо сообществу WinUI и всем контрибьюторам, которые помогают улучшать проект!
Lattice.UI.DragDrop.WinUI - часть Lattice UI Framework
GitHub • Документация • Discord • Twitter
