Это приложение должно отображать набор изображений в виде сетки (с несколькими столбцами).
Это приложение должно также:
- загрузить набор изображений из папки автозагрузки;
- разрешить перетаскивайте новые изображения в список;
- изменяйте порядок изображения в список;
- удалить изображения.
Мы можем исправить количество столбцов (4) и размер миниатюр (100x150).
Поскольку я не эксперт в WPF, я попробовал использовать два разных подхода, пока когда я углубляюсь в детали WPF.
Это первый подход:
Код: Выделить всё
Код: Выделить всё
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private ObservableCollection _imageItems;
private ImageItem _draggedItem;
private Point _dragStartPoint;
public MainWindow()
{
InitializeComponent();
_imageItems = new ObservableCollection();
LoadImagesFromFolder(Properties.Settings.Default.ImagesFolder); // Sostituisci con il percorso della tua cartella
PopulateGrid();
}
private void LoadImagesFromFolder(string folderPath)
{
if (Directory.Exists(folderPath))
{
var imageFiles = Directory.GetFiles(folderPath);
foreach (var imagePath in imageFiles)
{
if (IsImageFile(imagePath))
{
_imageItems.Add(new ImageItem { ImagePath = imagePath });
}
}
}
}
private bool IsImageFile(string filePath)
{
string[] validExtensions = { ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff" };
string fileExtension = Path.GetExtension(filePath).ToLower();
return Array.Exists(validExtensions, ext => ext == fileExtension);
}
private void PopulateGrid()
{
ThumbnailGrid.Children.Clear();
foreach (var imageItem in _imageItems)
{
var stackPanel = new StackPanel
{
Orientation = Orientation.Vertical
};
var imageControl = new Image
{
Source = new BitmapImage(new Uri(imageItem.ImagePath)),
Width = 100,
Height = 100,
Margin = new Thickness(5)
};
imageControl.MouseLeftButtonDown += ImageControl_MouseLeftButtonDown;
var deleteButton = new Button
{
Content = "Delete",
Margin = new Thickness(5)
};
deleteButton.Click += (s, e) => DeleteImage(imageItem);
stackPanel.Children.Add(imageControl);
stackPanel.Children.Add(deleteButton);
ThumbnailGrid.Children.Add(stackPanel);
}
}
private void DeleteImage(ImageItem imageItem)
{
_imageItems.Remove(imageItem);
PopulateGrid();
}
private void ImageControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Image image && image.Source is BitmapImage bitmapImage)
{
_dragStartPoint = e.GetPosition(null);
_draggedItem = new ImageItem { ImagePath = bitmapImage.UriSource.ToString() };
DragDrop.DoDragDrop(image, _draggedItem, DragDropEffects.Move);
}
}
private void ThumbnailGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_dragStartPoint = e.GetPosition(null);
}
private void ThumbnailGrid_Drop(object sender, DragEventArgs e)
{
HandleDrop(e);
}
private void Window_Drop(object sender, DragEventArgs e)
{
HandleDrop(e);
}
private void HandleDrop(DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] droppedFiles = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string filePath in droppedFiles)
{
if (IsImageFile(filePath))
{
_imageItems.Add(new ImageItem { ImagePath = filePath });
}
}
PopulateGrid();
}
else if (e.Data.GetDataPresent(typeof(ImageItem)))
{
var droppedItem = (ImageItem)e.Data.GetData(typeof(ImageItem));
var dropPosition = e.GetPosition(ThumbnailGrid);
var targetIndex = GetIndexFromPoint(dropPosition);
if (_draggedItem != null)
{
_imageItems.Remove(_draggedItem);
_imageItems.Insert(targetIndex, _draggedItem);
PopulateGrid();
}
}
}
private void Window_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Move;
}
private void ThumbnailGrid_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Move;
}
private int GetIndexFromPoint(Point point)
{
for (int i = 0; i < ThumbnailGrid.Children.Count; i++)
{
var element = ThumbnailGrid.Children[i] as UIElement;
if (element != null)
{
var bounds = VisualTreeHelper.GetDescendantBounds(element);
var mousePosition = element.TranslatePoint(point, ThumbnailGrid);
if (bounds.Contains(mousePosition))
{
return i;
}
}
}
return ThumbnailGrid.Children.Count;
}
}
}
Код: Выделить всё
Код: Выделить всё
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApp2
{
public partial class MainWindow : Window
{
public ObservableCollection Images { get; set; }
public MainWindow()
{
InitializeComponent();
Images = new ObservableCollection();
DataContext = this;
LoadImagesFromFolder(WpfApp2.Properties.Settings.Default.ImagesFolder);
}
private void LoadImagesFromFolder(string folderPath)
{
if (Directory.Exists(folderPath))
{
var imageFiles = Directory.GetFiles(folderPath)
.Where(IsImageFile);
foreach (var file in imageFiles)
{
Images.Add(file);
}
}
else
{
MessageBox.Show("The specified folder does not exist.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void Image_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (var file in files)
{
if (IsImageFile(file))
{
Images.Add(file);
}
}
}
}
private bool IsImageFile(string filePath)
{
string[] validExtensions = { ".jpg", ".jpeg", ".png", ".bmp", ".gif" };
string extension = Path.GetExtension(filePath)?.ToLower();
return validExtensions.Contains(extension);
}
private void DeleteImage(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.DataContext is string imagePath)
{
Images.Remove(imagePath);
}
}
private void Image_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && sender is Image image && image.DataContext is string imagePath)
{
DragDrop.DoDragDrop(image, imagePath, DragDropEffects.Move);
}
}
private void Image_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Move;
e.Handled = true;
}
private void Image_DropReorder(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.StringFormat))
{
string droppedImage = (string)e.Data.GetData(DataFormats.StringFormat);
if (sender is Image targetImage && targetImage.DataContext is string targetPath)
{
int oldIndex = Images.IndexOf(droppedImage);
int newIndex = Images.IndexOf(targetPath);
if (oldIndex >= 0 && newIndex >= 0 && oldIndex != newIndex)
{
Images.Move(oldIndex, newIndex);
}
}
}
}
}
}

Я не могу понять, в чем разница в макете xaml-файла, который ведет к этому различия в рендеринге....
Можно ли добиться правильного расположения сетки в рамках моего второго подхода?
Подробнее здесь: https://stackoverflow.com/questions/793 ... rid-layout
Мобильная версия