封装WPF中列表控件的剪贴板操作(附源码)

文章目录

  • 前言
  • 1.剪贴板功能演示
  • [2. 功能说明](#2. 功能说明)
    • [2.1 框选效果](#2.1 框选效果)
    • [2.2 复制](#2.2 复制)
    • [2.3 剪切](#2.3 剪切)
    • [2.4 粘贴](#2.4 粘贴)
    • [2.5 删除](#2.5 删除)
    • [2.6 键盘快捷键支持](#2.6 键盘快捷键支持)
    • [2.7 多语言支持](#2.7 多语言支持)
    • [2.8 跨应用程序支持](#2.8 跨应用程序支持)
  • 3.如何获取

前言

在WPF中,ListBox、ListView和DataGrid等控件原生不支持直接通过剪贴板批量操作数据(复制、剪切、粘贴),为了可以在不同的项目中复用剪贴板操作,我们可以将这个功能进行封装,这样我们就可以在新的项目中快速移植剪贴板功能。


1.剪贴板功能演示

2. 功能说明

2.1 框选效果

定义一个名为SelectorExtension静态扩展类,并 在该类中新建一个名为IsEnableDragSelection的附加属性,在属性的PropertyChangedCallback中订阅控件的鼠标按下、移动、松开事件,在事件处理方法中获取到鼠标的坐标及状态,并用装饰器添加框选效果。

2.2 复制

新建一个名为IsEnableCopy的附加属性,在属性的PropertyChangedCallback中获取到MenuItem,并为MenuItem添加ApplicationCommands.Copy命令绑定,然后实现复制功能。

命令绑定关键代码:

csharp 复制代码
menuItem.Command = ApplicationCommands.Copy;
selector.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy, CopyCmdExecuted, CopyCmdCanExecuted));

复制功能关键代码:

csharp 复制代码
var copyingItems = new List<string>();
foreach (var item in selectedItems)
{
    if (item is ICloneable obj)
    {
        copyingItems.Add(JsonSerializer.Serialize(obj.Clone()));
    }
    else
    {
        copyingItems.Add(JsonSerializer.Serialize(item));
    }
}
Clipboard.SetText(string.Join(Environment.NewLine, copyingItems));

2.3 剪切

新建一个名为IsEnableCut的附加属性,在属性的PropertyChangedCallback中获取到MenuItem,并为MenuItem添加ApplicationCommands.Cut命令绑定,然后实现剪切功能。

命令绑定关键代码:

csharp 复制代码
menuItem.Command = ApplicationCommands.Cut;
selector.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, CutCmdExecuted, CutCmdCanExecuted));

剪切功能关键代码:

csharp 复制代码
var removeItems = new List<object>();
var cuttingItems = new List<string>();
foreach (var item in selectedItems)
{
    removeItems.Add(item);
    cuttingItems.Add(JsonSerializer.Serialize(item));
}
Clipboard.SetText(string.Join(Environment.NewLine, cuttingItems));
foreach (var item in removeItems)
{
    if (items.Contains(item))
    {
        items.Remove(item);
    }
}

2.4 粘贴

新建一个名为IsEnablePaste的附加属性,在属性的PropertyChangedCallback中获取到MenuItem,并为MenuItem添加ApplicationCommands.Paste命令绑定,然后实现粘贴功能。

命令绑定关键代码:

csharp 复制代码
menuItem.Command = ApplicationCommands.Paste;
selector.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, PasteCmdExecuted, PasteCmdCanExecuted));

粘贴功能关键代码:

csharp 复制代码
var clipboardObjects = GetClipboardObject(selector);
if (clipboardObjects != null)
{
    var selectedItems = selector.GetSelectedItems();
    if (selector.ItemsSource is IList items)
    {
        var length = selectedItems.Count;
        if (length == 0)
        {
            // 未选中
            foreach (var clipboardObject in clipboardObjects)
            {
                items.Add(clipboardObject);
                selectedItems.Add(clipboardObject);
            }
        }
        else
        {
            // 已选中               
            int index = items.IndexOf(selectedItems[length - 1]);
            selectedItems.Clear();
            foreach (var clipboardObject in clipboardObjects)
            {
                items.Insert(index, clipboardObject);
                selectedItems.Add(clipboardObject);
                index++;
            }
        }
    }
}

2.5 删除

新建一个名为IsEnableDelete的附加属性,在属性的PropertyChangedCallback中获取到MenuItem,并为MenuItem添加ApplicationCommands. Delete命令绑定,然后实现删除功能。
命令绑定关键代码:

csharp 复制代码
menuItem.Command = ApplicationCommands.Delete;
selector.CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, DeleteCmdExecuted, DeleteCmdCanExecuted));

删除功能关键代码:

csharp 复制代码
var selectedItems = selector.GetSelectedItems();
if (selector.ItemsSource is IList items &&
    selectedItems != null &&
    selectedItems.Count > 0)
{
    var removeItems = new List<object>();
    foreach (var item in selectedItems)
    {
        removeItems.Add(item);
    }
    foreach (var item in removeItems)
    {
        if (items.Contains(item))
        {
            items.Remove(item);
        }
    }
}

2.6 键盘快捷键支持

以上代码支持键盘组合键Ctrl+C(复制)、Ctrl+X(剪切)、Ctrl+V(粘贴)、Delete(删除)。

2.7 多语言支持

以上代码支持自动语言切换。

2.8 跨应用程序支持

使用Json转换对象,剪贴板中存储的是Json字符串,可以支持跨应用程序复制粘贴。

3.如何获取

完整源代码已经上传到群(661224882)文件,如有需要,请自行获取。

技术赋能,共创未来

我们是一支深耕WPF及Avalonia十余年的开发团队,专注于为企业和开发者提供高性能桌面应用解决方案,目前已经为二十多家企业提供过服务,无论您是哪种需求,我们都可以用我们丰富的经验助力您的业务高效落地。如果您有相关需求,请与我们联系。

联系方式

QQ/VX:446522563

手机号:17898179019

技术交流

QQ群:661224882

相关推荐
Macbethad17 小时前
如何用WPF做工控设置界面
java·开发语言·wpf
csdn_aspnet17 小时前
WPF 做一个简单的电子签名板(一)
c#·wpf
玖笙&17 小时前
✨WPF编程进阶【7.2】:动画类型(附源码)
c++·c#·wpf·visual studio
·心猿意码·1 天前
WPF中TemplatePart机制详解
wpf
FuckPatience2 天前
WPF 使用UserControl / ContentControl显示子界面
wpf
wangnaisheng3 天前
【WPF】WrapPanel的用法
wpf
源之缘-OFD先行者3 天前
10 万雷达点迹零卡顿回放:WPF + Vortice.Direct2D 多线程渲染实战
wpf
猫林老师3 天前
Flutter for HarmonyOS开发指南(九):测试、调试与质量保障体系
flutter·wpf·harmonyos
LateFrames4 天前
做【秒开】的程序:WPF / WinForm / WinUI3 / Electron
electron·c#·wpf·winform·winui3·claude code
beyond谚语4 天前
第四章 依赖项属性
wpf