547 lines
17 KiB
Markdown
547 lines
17 KiB
Markdown
# Lattice.UI.DragDrop.WinUI
|
||
|
||

|
||

|
||

|
||

|
||

|
||
|
||
Полнофункциональная реализация системы перетаскивания для WinUI 3 в составе Lattice UI Framework.
|
||
|
||
## 🎉 Демо
|
||
|
||

|
||
|
||
*Перетаскивание элементов между контейнерами и переупорядочивание списка*
|
||
|
||
## 📦 Особенности
|
||
|
||
✅ **Готовое решение для WinUI 3** - работает из коробки
|
||
✅ **Attached Behaviors** - легко подключается к любым UIElement
|
||
✅ **Визуальная обратная связь** - анимации и подсветка
|
||
✅ **Переупорядочивание элементов** - drag-and-drop в списках
|
||
✅ **Кастомизация стилей** - полный контроль над внешним видом
|
||
✅ **Поддержка сложных сценариев** - вложенные элементы, зоны сброса
|
||
✅ **Производительность** - оптимизировано для плавной работы
|
||
|
||
## 🚀 Быстрый старт
|
||
|
||
### 1. Установка
|
||
|
||
Добавьте пакет через NuGet:
|
||
|
||
```powershell
|
||
Install-Package Lattice.UI.DragDrop.WinUI
|
||
```
|
||
|
||
Или через Package Manager:
|
||
|
||
```xml
|
||
<PackageReference Include="Lattice.UI.DragDrop.WinUI" Version="1.0.0" />
|
||
```
|
||
|
||
### 2. Инициализация в приложении
|
||
|
||
```csharp
|
||
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();
|
||
}
|
||
```
|
||
|
||
## 🎨 Использование
|
||
|
||
### Базовое перетаскивание
|
||
|
||
```csharp
|
||
// Создаем перетаскиваемый элемент
|
||
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));
|
||
```
|
||
|
||
### Переупорядочивание элементов в списке
|
||
|
||
```csharp
|
||
// Создаем контейнер с поддержкой переупорядочивания
|
||
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);
|
||
}
|
||
```
|
||
|
||
### Кастомизация визуальной обратной связи
|
||
|
||
```csharp
|
||
// Создаем кастомный стиль
|
||
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 (Расширения)
|
||
|
||
```csharp
|
||
// Основные методы расширения
|
||
element.MakeDragSource(data); // Сделать перетаскиваемым
|
||
element.MakeDropTarget(types); // Сделать целью сброса
|
||
control.ApplyDragStyle(); // Применить стиль перетаскивания
|
||
control.SetDragVisualState("Dragging"); // Установить визуальное состояние
|
||
```
|
||
|
||
## 🎯 Примеры использования
|
||
|
||
### Пример 1: Файловый менеджер
|
||
|
||
```csharp
|
||
// Перетаскивание файлов
|
||
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
|
||
|
||
```csharp
|
||
// Панель инструментов
|
||
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: Календарь с событиями
|
||
|
||
```csharp
|
||
// Событие календаря
|
||
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` - общие стили для элементов
|
||
|
||
### Кастомизация через ресурсы
|
||
|
||
```xml
|
||
<!-- 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` - над элементом перетаскивают объект
|
||
|
||
```csharp
|
||
// Переключение состояний
|
||
control.SetDragVisualState("Dragging", true); // С анимацией
|
||
control.SetDragVisualState("Normal", false); // Без анимации
|
||
```
|
||
|
||
## 🔧 Интеграция с Docking System
|
||
|
||
Система идеально интегрируется с Lattice Docking:
|
||
|
||
```csharp
|
||
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());
|
||
}
|
||
}
|
||
```
|
||
|
||
## 📊 Производительность
|
||
|
||
### Оптимизации
|
||
|
||
1. **Минимальные перерисовки** - обновление только при необходимости
|
||
2. **Кэширование визуальных элементов** - повторное использование
|
||
3. **Эффективные алгоритмы поиска** - быстрый поиск целей сброса
|
||
4. **Асинхронная обработка** - не блокирует UI поток
|
||
|
||
### Рекомендации
|
||
|
||
```csharp
|
||
// ✅ Правильно
|
||
element.MakeDragSource(data);
|
||
|
||
// ❌ Избегать
|
||
element.PointerPressed += (s, e) => { /* сложная логика */ };
|
||
element.PointerMoved += (s, e) => { /* частые обновления */ };
|
||
```
|
||
|
||
## 🧪 Тестирование
|
||
|
||
### Модульные тесты
|
||
|
||
```csharp
|
||
[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 тесты
|
||
|
||
```csharp
|
||
[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);
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🔍 Отладка
|
||
|
||
### Включение логов
|
||
|
||
```csharp
|
||
// Включение подробного логирования
|
||
#if DEBUG
|
||
DragDropDebugger.EnableLogging = true;
|
||
DragDropDebugger.LogLevel = LogLevel.Verbose;
|
||
#endif
|
||
```
|
||
|
||
### Визуальные подсказки
|
||
|
||
```csharp
|
||
// Показать границы целей сброса
|
||
DebugDropTargets.ShowBounds = true;
|
||
|
||
// Показать траекторию перетаскивания
|
||
DebugDragTrail.Enabled = true;
|
||
DebugDragTrail.Color = Colors.Red;
|
||
```
|
||
|
||
## 📈 Производительность в production
|
||
|
||
### Мониторинг
|
||
|
||
```csharp
|
||
// Сбор метрик
|
||
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}");
|
||
```
|
||
|
||
### Оптимизация для больших списков
|
||
|
||
```csharp
|
||
// Виртуализация для списков
|
||
var virtualizingList = new ListView
|
||
{
|
||
ItemsSource = largeCollection,
|
||
VirtualizingStackPanel.VirtualizationMode = VirtualizationMode.Recycling
|
||
};
|
||
|
||
// Оптимизация перетаскивания
|
||
virtualizingList.MakeDropTarget(typeof(DataItem));
|
||
virtualizingList.SetDragDropOptimization(true);
|
||
```
|
||
|
||
## 🤝 Интеграция с другими компонентами Lattice
|
||
|
||
### Toolbox
|
||
```csharp
|
||
toolboxItem.MakeDragSource(new ToolboxItem
|
||
{
|
||
Type = typeof(Button),
|
||
Icon = "🔘"
|
||
});
|
||
```
|
||
|
||
### Property Grid
|
||
```csharp
|
||
propertyItem.MakeDragSource(new PropertyValue
|
||
{
|
||
Name = "Background",
|
||
Value = Colors.Blue
|
||
});
|
||
```
|
||
|
||
### Layout System
|
||
```csharp
|
||
layoutPanel.MakeDropTarget(typeof(UIElement));
|
||
layoutPanel.SetDropPositionHandler((element, position) =>
|
||
{
|
||
return CalculateDropZone(position);
|
||
});
|
||
```
|
||
|
||
## 📚 Дополнительные ресурсы
|
||
|
||
### Документация
|
||
- [Полная документация API](https://lattice-framework.github.io/ui-dragdrop/api/)
|
||
- [Примеры использования](https://lattice-framework.github.io/ui-dragdrop/examples/)
|
||
- [Руководство по стилизации](https://lattice-framework.github.io/ui-dragdrop/styling/)
|
||
|
||
### Видео туториалы
|
||
- [Быстрый старт](https://youtube.com/playlist?list=...) - 15 минут
|
||
- [Продвинутые техники](https://youtube.com/playlist?list=...) - 45 минут
|
||
- [Интеграция с Docking](https://youtube.com/playlist?list=...) - 30 минут
|
||
|
||
### Сообщество
|
||
- [GitHub Discussions](https://github.com/lattice-framework/ui-dragdrop/discussions) - вопросы и обсуждения
|
||
- [Discord](https://discord.gg/lattice) - живое общение
|
||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/lattice-ui-dragdrop) - технические вопросы
|
||
|
||
## 🐛 Отчет об ошибках
|
||
|
||
Нашли ошибку? [Создайте issue](https://github.com/lattice-framework/ui-dragdrop/issues) с подробным описанием:
|
||
|
||
1. Шаги для воспроизведения
|
||
2. Ожидаемое поведение
|
||
3. Фактическое поведение
|
||
4. Скриншоты или видео
|
||
5. Версии: 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](LICENSE).
|
||
|
||
## 👥 Авторы
|
||
|
||
- **Команда Lattice Framework** - [@lattice-framework](https://github.com/lattice-framework)
|
||
- **Главный разработчик** - [Ваше имя](https://github.com/yourusername)
|
||
|
||
## 🙏 Благодарности
|
||
|
||
Спасибо сообществу WinUI и всем контрибьюторам, которые помогают улучшать проект!
|
||
|
||
---
|
||
|
||
<div align="center">
|
||
<p>
|
||
<strong>Lattice.UI.DragDrop.WinUI</strong> - часть <a href="https://github.com/lattice-framework">Lattice UI Framework</a>
|
||
</p>
|
||
<p>
|
||
<a href="https://github.com/lattice-framework/ui-dragdrop">GitHub</a> •
|
||
<a href="https://lattice-framework.github.io">Документация</a> •
|
||
<a href="https://discord.gg/lattice">Discord</a> •
|
||
<a href="https://twitter.com/latticefw">Twitter</a>
|
||
</p>
|
||
</div> |