5

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

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

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

我找不到任何临时禁用菜单项键盘快捷键的方法,而无需手动存储旧快捷键,将快捷键设置为空,然后在需要重新启用时将其复制回来(感觉很脏)。

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

4

1 回答 1

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)*/ }
    }
}

要使用您将创建类,然后在和事件guardedCommand.CurrentlyEditing中根据需要设置它的属性。然后,无论您在何处捕获 CTRL+C 快捷方式,只需调用它,它就会处理其余的事情。BeforeLabelEditAfterLabelEditguardedCommand.DoCopy()

如果您正在阅读有关您想要做的事情的模式,那么请查看State Pattern,上面的代码就是其中的一种和实现。要成为一个真正的状态(或策略)模式,它需要有单独的具体类来实现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();
        }
    }
}

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

于 2012-09-18T19:44:57.283 回答