Files
Lattice/Lattice.Example.DragDrop/MainWindow.xaml.cs
2026-01-25 07:56:35 +03:00

421 lines
13 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 Lattice.Core.DragDrop.Services;
using Lattice.Themes;
using Lattice.UI.DragDrop.WinUI.Factories;
using Lattice.UI.DragDrop.WinUI.Services;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
namespace Lattice.Example.DragDrop;
public sealed partial class MainWindow : Window
{
private readonly ObservableCollection<DragDropItem> _sourceItems = new();
private readonly ObservableCollection<DragDropItem> _droppedItems = new();
private WinUIDragDropManager? _dragDropManager;
private IDragDropService? _dragDropService;
private int _dragOperationCount = 0;
public MainWindow()
{
// Создаем менеджер перетаскивания
_dragDropManager = WinUIDragDropFactory.CreateManager(this, manager =>
{
// Настраиваем смещение визуального элемента
manager.DragVisualOffset = new Core.Geometry.Point(-15, -15);
});
_dragDropService = _dragDropManager.DragDropService;
InitializeComponent();
// Устанавливаем размер окна
SetWindowSize(1200, 800);
// Инициализируем данные
InitializeData();
// Инициализируем drag & drop систему
InitializeDragDrop();
// Устанавливаем контекст данных
SourceItemsControl.ItemsSource = _sourceItems;
DroppedItemsControl.ItemsSource = _droppedItems;
Closed += MainWindow_Closing;
// Обновляем видимость инструкций
UpdateDropInstructions();
}
private void MainWindow_Closing(object sender, WindowEventArgs args)
{
// Очищаем ресурсы
_dragDropManager?.Dispose();
}
private void InitializeData()
{
// Создаем тестовые данные для перетаскивания
_sourceItems.Add(new DragDropItem
{
Name = "Document",
Description = "Microsoft Word document",
Icon = "Document",
Type = "File"
});
_sourceItems.Add(new DragDropItem
{
Name = "Image",
Description = "PNG image file",
Icon = "Pictures",
Type = "File"
});
_sourceItems.Add(new DragDropItem
{
Name = "Music",
Description = "MP3 audio file",
Icon = "Audio",
Type = "File"
});
_sourceItems.Add(new DragDropItem
{
Name = "Video",
Description = "MP4 video file",
Icon = "Video",
Type = "File"
});
_sourceItems.Add(new DragDropItem
{
Name = "Contact",
Description = "Contact information",
Icon = "Contact",
Type = "Data"
});
_sourceItems.Add(new DragDropItem
{
Name = "Link",
Description = "Web URL",
Icon = "Link",
Type = "Link"
});
_sourceItems.Add(new DragDropItem
{
Name = "Folder",
Description = "File system folder",
Icon = "Folder",
Type = "Folder"
});
}
private void InitializeDragDrop()
{
try
{
// Настраиваем кастомный источник перетаскивания
_dragDropManager.MakeDragSource(CustomDragSource, new DragDropItem
{
Name = "Custom Element",
Description = "This is a custom drag source example",
Icon = "Favorite",
Type = "Custom"
});
// Настраиваем обработчик для области сброса
_dragDropManager.MakeDropTarget(DropTargetArea);
// Подписываемся на события перетаскивания
_dragDropService.DragStarted += OnDragStarted;
_dragDropService.DragUpdated += OnDragUpdated;
_dragDropService.DragCompleted += OnDragCompleted;
_dragDropService.DragCancelled += OnDragCancelled;
_dragDropService.DropTargetChanged += OnDropTargetChanged;
_dragDropService.ErrorOccurred += OnDragDropError;
UpdateStats();
StatusText.Text = "Drag & Drop system initialized";
}
catch (Exception ex)
{
StatusText.Text = $"Failed to initialize Drag & Drop: {ex.Message}";
ShowErrorDialog("Initialization Error", ex.Message);
}
}
private void OnDragStarted(object? sender, Core.DragDrop.Services.DragStartedEventArgs e)
{
_dragOperationCount++;
UpdateStats();
StatusText.Text = $"Dragging started: {GetItemName(e.DragInfo.Data)}";
}
private void OnDragUpdated(object? sender, Core.DragDrop.Services.DragUpdatedEventArgs e)
{
StatusText.Text = $"Dragging: {GetItemName(e.DragInfo.Data)} at ({e.Position.X:F0}, {e.Position.Y:F0})";
}
private void OnDragCompleted(object? sender, Core.DragDrop.Services.DragCompletedEventArgs e)
{
// Проверяем, что элемент сброшен на нашу область
if (e.DragInfo.Data is DragDropItem item)
{
// Добавляем элемент в список сброшенных
DispatcherQueue.TryEnqueue(() =>
{
if (!_droppedItems.Contains(item))
{
_droppedItems.Add(item);
// Удаляем из источников, если это не кастомный элемент
if (_sourceItems.Contains(item) && item.Name != "Custom Element")
{
_sourceItems.Remove(item);
}
UpdateStats();
UpdateDropInstructions();
StatusText.Text = $"Item dropped: {item.Name}";
// Показываем уведомление
ShowDropNotification(item);
}
});
}
else
{
StatusText.Text = "Drag completed";
}
}
private async void ShowDropNotification(DragDropItem item)
{
var notification = new TeachingTip
{
Title = "Item Dropped",
Subtitle = $"Successfully dropped '{item.Name}'",
IsOpen = true,
PreferredPlacement = TeachingTipPlacementMode.TopRight,
Target = DropTargetArea
};
// Автоматически скрываем через 3 секунды
await Task.Delay(3000);
notification.IsOpen = false;
}
private void OnDragCancelled(object? sender, Core.DragDrop.Services.DragCancelledEventArgs e)
{
StatusText.Text = "Drag cancelled";
}
private void OnDropTargetChanged(object? sender, Core.DragDrop.Services.DropTargetChangedEventArgs e)
{
if (e.Target != null)
{
StatusText.Text = "Over drop target";
}
else
{
StatusText.Text = "Not over drop target";
}
}
private async void OnDragDropError(object? sender, Core.DragDrop.Services.DragDropErrorEventArgs e)
{
StatusText.Text = $"Error: {e.Exception.Message}";
await ShowErrorDialog("Drag & Drop Error", e.Exception.Message);
}
private string GetItemName(object? data)
{
if (data is DragDropItem item)
{
return item.Name;
}
return data?.ToString() ?? "Unknown";
}
private void UpdateStats()
{
DispatcherQueue.TryEnqueue(() =>
{
DragStatsText.Text = $"Drag operations: {_dragOperationCount}";
DropStatsText.Text = $"Dropped items: {_droppedItems.Count}";
});
}
private void UpdateDropInstructions()
{
DropInstructionsBorder.Visibility = _droppedItems.Count == 0 ?
Visibility.Visible : Visibility.Collapsed;
}
private void OnThemeToggleToggled(object sender, RoutedEventArgs e)
{
if (sender is ToggleSwitch toggle)
{
try
{
var themeManager = ThemeManager.Current;
if (toggle.IsOn)
{
themeManager.ApplyTheme("Fluent Dark");
}
else
{
themeManager.ApplyTheme("Fluent");
}
StatusText.Text = $"Theme changed to {(toggle.IsOn ? "Dark" : "Light")}";
}
catch (Exception ex)
{
StatusText.Text = $"Failed to change theme: {ex.Message}";
}
}
}
private async void OnStatsButtonClick(object sender, RoutedEventArgs e)
{
if (_dragDropService != null)
{
var stats = _dragDropService.GetStats();
var dialog = new ContentDialog
{
Title = "Drag & Drop Statistics",
Content = new ScrollViewer
{
Content = new StackPanel
{
Spacing = 8,
Children =
{
CreateStatRow("Total Drag Operations:", stats.TotalDragOperations.ToString()),
CreateStatRow("Successful Drops:", stats.SuccessfulDrops.ToString()),
CreateStatRow("Cancelled Operations:", stats.CancelledOperations.ToString()),
CreateStatRow("Errors:", stats.ErrorCount.ToString()),
CreateStatRow("Registered Targets:", stats.RegisteredTargets.ToString()),
CreateStatRow("Average Operation Time:",
stats.AverageOperationTime.TotalMilliseconds.ToString("F0") + "ms")
}
}
},
PrimaryButtonText = "OK",
XamlRoot = Content.XamlRoot
};
await dialog.ShowAsync();
}
}
private StackPanel CreateStatRow(string label, string value)
{
return new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 10,
Children =
{
new TextBlock
{
Text = label,
FontWeight = Microsoft.UI.Text.FontWeights.SemiBold,
Width = 200
},
new TextBlock
{
Text = value
}
}
};
}
private void OnRemoveItemClick(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.Tag is DragDropItem item)
{
_droppedItems.Remove(item);
UpdateStats();
UpdateDropInstructions();
// Добавляем обратно в источники, если это не кастомный элемент
if (item.Name != "Custom Element" && !_sourceItems.Contains(item))
{
_sourceItems.Add(item);
}
StatusText.Text = $"Item removed: {item.Name}";
}
}
private void OnResetPanelsClick(object sender, RoutedEventArgs e)
{
// Очищаем все сброшенные элементы
foreach (var item in _droppedItems.ToList())
{
if (item.Name != "Custom Element" && !_sourceItems.Contains(item))
{
_sourceItems.Add(item);
}
}
_droppedItems.Clear();
UpdateStats();
UpdateDropInstructions();
StatusText.Text = "Panels reset";
}
private async Task ShowErrorDialog(string title, string message)
{
var dialog = new ContentDialog
{
Title = title,
Content = message,
PrimaryButtonText = "OK",
XamlRoot = Content.XamlRoot
};
await dialog.ShowAsync();
}
// Метод для установки размера окна
private void SetWindowSize(int width, int height)
{
try
{
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hwnd);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.Resize(new Windows.Graphics.SizeInt32(width, height));
// Центрируем окно
var displayArea = Microsoft.UI.Windowing.DisplayArea.GetFromWindowId(windowId,
Microsoft.UI.Windowing.DisplayAreaFallback.Primary);
var centerX = (displayArea.WorkArea.Width - width) / 2;
var centerY = (displayArea.WorkArea.Height - height) / 2;
appWindow.Move(new Windows.Graphics.PointInt32(centerX, centerY));
}
catch (Exception ex)
{
// Игнорируем ошибки при установке размера окна
System.Diagnostics.Debug.WriteLine($"Failed to set window size: {ex.Message}");
}
}
}