使用C#winforms自定义复制/粘贴行为,同时允许文本编辑复制/粘贴

Mic*_*ker 5 c# events copy-paste winforms

我目前有一个C#winforms应用程序,Ctrl + C和Ctrl + V绑定为编辑主菜单上的键盘快捷键.代码中有一些自定义复制/粘贴行为,它们响应这些菜单项,例如复制和粘贴listviews中的行.

但是,我的问题是您可以编辑行内的文本,当您这样做时,我希望Ctrl + C和Ctrl + V不会触发编辑菜单命令,而应该默认为基于正常文本的复制/粘贴.

我尝试过的一件事是触发BeforeLabelEdit和AfterLabelEdit事件,并从那里手动禁用/重新启用菜单项.不幸的是,似乎禁用的菜单项上的键盘快捷键仍会触发menu_Popup事件,该事件当前用于决定应启用/禁用哪些菜单项.(例如,"粘贴"仅在剪贴板上有文本时才有效).因此,即使禁用菜单项,键盘快捷键仍将激活Popup事件,这将重新启用菜单项.(这是一个错误吗?)

我找不到任何临时禁用菜单项键盘快捷方式的方法,无需手动存储旧快捷方式,将快捷方式设置为null,然后在需要重新启用时感觉脏(但感觉很脏).

当然要覆盖复制/粘贴行为或添加它,这是常见的事情吗?这里有更好的模式吗?

Mat*_*ein 0

如果您想覆盖默认的复制/粘贴行为,您似乎需要使用比 C# 提供的更低级别的东西(请参阅剪贴板事件 C#检测和区分剪贴板事件(剪切、复制和粘贴))。但是,也许您可​​以将您的逻辑放在“守卫”后面,该“守卫”知道如何引导操作请求(如“复制”),然后将其重定向为适当的。

这是一个示例类:

namespace Your.App
{
    public class GuardedCommand
    {
        public bool CurrentlyEditing { get; set; }
        public GuardedCommand()
        {
            CurrentlyEditing = false;
        }
        public void DoCopy()
        {
            if(CurrentlyEditing)
                StandardCopyCommand();
            else
                ShortcutCopyCommand();
        }
        void ShortcutCopyCommand() { /*menu work here (or delegate to another class)*/ }
        void StandardCopyCommand() { /*"normal" work here (or delegate again)*/ }
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用该类,您需要创建该类,然后在和事件guardedCommand.CurrentlyEditing中适当设置其属性。然后,无论您在哪里按下 CTRL+C 快捷键,只需调用,它就会处理剩下的事情。BeforeLabelEditAfterLabelEditguardedCommand.DoCopy()

如果您想了解您想要做的事情的模式,请查看状态模式,上面的代码就是它的一种和实现。要成为真正的状态(或策略)模式,它需要有单独的具体类来实现DoCopy(),而DoPaste()不仅仅是使用 if/else 或 switch。然后,当CurrentlyEditing更改时,正确的具体实现将被设置为用于处理该DoCopy()方法的当前类。

仅仅因为我写该段花了比只给你一些代码更长的时间,所以这里有一些代码:

namespace Your.App
{
//correct implementation of the State Pattern
    interface IClipboard
    {
        void Copy();
        void Paste();
    }
    class MyCustomClipboard : IClipboard
    {
        public void Copy() { /*your special code*/ }
        public void Paste() { /*your code again*/ }
    }
    class DefaultClipboard : IClipboard
    {
        public void Copy() { /*default code*/ }
        public void Paste() { /*default code again*/ }
    }
    public class StateClass
    {
        IClipboard State { get; set; }
        public StateClass()
        {
            CurrentlyEditing = false;
        }
        bool _currentlyEditing;
        public bool CurrentlyEditing
        {
            get { return _currentlyEditing; }
            set
            {
                _currentlyEditing = value;
                if(_currentlyEditing)
                    State = new DefaultClipboard();
                else
                    State = new MyCustomClipboard();
            }
        }
        public void Copy()
        {
            State.Copy();
        }
        public void Paste()
        {
            State.Paste();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当只有两个状态时,这可能有点矫枉过正(并且状态数量可能不会增加)。