Макет сетки WPFC#

Место общения программистов C#
Ответить
Anonymous
 Макет сетки WPF

Сообщение Anonymous »

Я пишу простое приложение WPF .Net 4.8.
Это приложение должно отображать набор изображений в виде сетки (с несколькими столбцами).
Это приложение должно также:
  • загрузить набор изображений из папки автозагрузки;
  • разрешить перетаскивайте новые изображения в список;
  • изменяйте порядок изображения в список;
  • удалить изображения.
Конечно, количество изображений непредсказуемо с момента запуска папка также может быть пустой.
Мы можем исправить количество столбцов (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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»