using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Microsoft.Win32;
using NeoUI.Utilities;
namespace NeoUI.Controls;
///
/// 上传状态枚举,用于表示文件上传过程中的不同状态。该枚举包含三个可能的值:Pending(待处理)、Success(成功)和Error(错误)。
/// Pending 表示文件正在等待被上传;Success 表示文件已经成功上传;而 Error 则表示在尝试上传文件时发生了错误。
///
public enum UploadStatus
{
///
/// 表示文件或文件夹正处于待上传状态。当此枚举成员被设置时,意味着相关联的文件或文件夹已经准备好但还未开始实际的上传过程。
///
Pending,
///
/// 表示文件已成功上传。当此枚举成员被设置时,意味着所选文件或文件夹已经顺利完成上传过程。
///
Success,
///
/// 表示在尝试上传文件时发生了错误。当此枚举成员被设置时,表示文件上传过程中遇到了问题,未能成功完成。
///
Error
}
///
/// 上传文件项类,用于表示单个待上传的文件。此类实现了INotifyPropertyChanged接口,以便在属性更改时通知UI进行更新。
/// 每个实例包含文件路径、文件名及当前上传状态等信息。通过构造函数初始化时,会自动设置文件名,并将上传状态设为Pending(待处理)。
///
public class UploadFileItem : INotifyPropertyChanged
{
private string filePath;
///
/// 获取或设置当前文件项的完整路径。
///
public string FilePath
{
get => filePath;
set => SetField(ref filePath, value);
}
private string fileName;
///
/// 获取或设置当前文件项的文件名。
///
public string FileName
{
get => fileName;
set => SetField(ref fileName, value);
}
private UploadStatus status;
///
/// 获取或设置当前文件项的上传状态。状态可以是Pending(待处理)、Success(成功)或Error(错误)。
///
public UploadStatus Status
{
get => status;
set => SetField(ref status, value);
}
///
/// 上传文件项类,用于表示单个待上传的文件。此类实现了INotifyPropertyChanged接口,以便在属性更改时通知UI进行更新。
/// 每个实例包含文件路径、文件名及当前上传状态等信息。通过构造函数初始化时,会自动设置文件名,并将上传状态设为Pending(待处理)。
///
public UploadFileItem(string filePath)
{
FilePath = filePath;
FileName = Path.GetFileName(filePath);
Status = UploadStatus.Pending;
}
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// 当属性值更改时调用此方法,以通知UI进行相应的更新。
/// 该方法会触发PropertyChanged事件,并传递更改的属性名称作为参数。
///
/// 可选参数,指定触发属性更改事件的属性名。如果未提供,则默认使用调用者成员名称。
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
///
/// 设置指定字段的值,并在值更改时触发属性更改通知。
/// 如果新值与旧值相同,则不会进行任何操作也不会触发通知。
///
/// 字段的数据类型。
/// 要设置值的字段。
/// 要赋予字段的新值。
/// 可选参数,指定触发属性更改事件的属性名。如果未提供,则默认使用调用者成员名称。
/// 如果值被成功设置且不等于旧值返回true;否则返回false。
protected bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer.Default.Equals(field, value)) return false;
field = value;
if (propertyName != null) OnPropertyChanged(propertyName);
return true;
}
}
///
/// 上传区域控件,用于实现文件或文件夹的拖拽上传功能。支持设置可接受的上传内容类型(仅文件或仅文件夹)、是否允许多选、文件过滤器以及主提示文字等属性。
/// 控件还提供了对拖放事件的支持,允许用户通过拖拽文件到该区域内来完成上传操作,并且能够显示已选择的文件列表。
///
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "DragOver", GroupName = "DragDropStates")]
[TemplateVisualState(Name = "DragLeave", GroupName = "DragDropStates")]
public class UploadArea : Control
{
private bool isDragOver;
#region Commands
///
/// 定义一个命令,用于从文件列表中移除指定的文件项。
///
public ICommand RemoveItemCommand { get; }
///
/// 获取用于触发选择文件或文件夹操作的命令。此命令绑定到控件,允许用户通过点击来选择文件或文件夹。
///
public ICommand SelectCommand { get; }
#endregion
static UploadArea()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(UploadArea), new FrameworkPropertyMetadata(typeof(UploadArea)));
}
///
/// 上传区域控件,允许用户通过点击或拖拽方式上传文件或文件夹。支持设置接受的文件类型、是否允许多选以及提示文本等属性。
///
public UploadArea()
{
FileList = [];
RemoveItemCommand = new RelayCommand(p => FileList.Remove(p as UploadFileItem));
SelectCommand = new RelayCommand