6

I currently have a C# winforms app with Ctrl+C and Ctrl+V bound as keyboard shortcuts on the Edit main menu. There is some custom copy/paste behaviour inside code which responds to these menu items, such as copying and pasting rows in listviews.

However, my problem is that you can edit text inside a row, and when you do so, I want Ctrl+C and Ctrl+V to not trigger the edit menu command and should rather default to the normal text based copy/paste.

One thing I tried is triggering BeforeLabelEdit and AfterLabelEdit events, and manually disabling/re-enabling the menu items from inside there. Unfortunately, it seems that a keyboard shortcut on a disabled menu item still triggers the menu_Popup event, which is currently used to decide which menu items should be enabled/disabled. (For example, "Paste" is only active if there is text on the clipboard). So even if I disable the menu item, the keyboard shortcut will still activate the Popup event, which will re-enable the menu item. (Is this a bug?)

I can't find any method of temporarily disabling a menu items keyboard shortcut without manually storing the old shortcut, setting the shortcut to null, then copying it back when I need to re-enable (which feels dirty).

Surely overriding the copy/paste behaviour, or adding to it, is a common thing to want to do? Is there a better pattern to use here?

Michael Parker
  • 7,180
  • 7
  • 30
  • 39
  • ovveriding copy paste sounds as a bad idea to me. i am used to `copy/paste` it always works the same on all apps. your app will just confuse me. but if u insist, why not check the focus? if focus is on your text box do one copy paste if isn't do the other – Nahum Sep 12 '12 at 13:36
  • Our custom copy/paste behaviour only deals with copying and pasting rows when you are not editing text. I want default copy/paste behaviour when you are editing text. – Michael Parker Sep 12 '12 at 14:21
  • 2
    Clearing the menu's shortcut key is the easiest way. Other alternatives will be 'dirtier'. – John Arlen Sep 15 '12 at 09:20

1 Answers1

0

It looks like you'll need to use something lower level than C# offers if you want to override the default copy/paste behavior (see Clipboard event C# and Detect & Differentiate Clipboard Events (Cut,Copy and Paste)). However, perhaps you could put your logic behind a "guard" that knows how to direct a request for action (like the "Copy") and then redirect it as approprite.

Here is a sample class:

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

To use you would create the class, then set it's guardedCommand.CurrentlyEditing property as appropriate in the BeforeLabelEdit and AfterLabelEdit events. Then, whereever you catch the CTRL+C shortcut, just invoke guardedCommand.DoCopy() and it will take care of the rest.

If you're looking to read about a pattern for what you're looking to do, then check out the State Pattern, which the above code is sort of and implementation of. To be a real State (or Strategy) Pattern it would need to have seperate concrete classes that implement DoCopy() and DoPaste() rather than just using an if/else or switch. Then, when CurrentlyEditing is being changed, the proper concrete implementation would be set as the current class used to handle the DoCopy() method.

And just because it took me longer to write that paragraph than it would have to just give you some code, here's some code:

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();
        }
    }
}

As you can see, this may be a bit overkill when there are only two states (and the number of states probably won't increase).

Community
  • 1
  • 1
Matt Klein
  • 7,856
  • 6
  • 45
  • 46
  • Does this mean that I would need to code the default copy/paste behaviour myself? This is something I was hoping to avoid. Also, does this mean I would not be able to list the commands on the menu in the shortcut key columnn on the right? What's surprising to me is that by default, the KeyDown method does not capture Ctrl+C when i am editing a label, but it does when I am not editing it (which is useful). This is different behaviour than the menu shortcut keys, which when assigned, will trigger whether I am editing or not. – Michael Parker Sep 20 '12 at 15:31
  • Sorry, for some reason I got the impression that you had code to use the default copy/paste already implemented. After re-reading your question I see that you never mention that. I suspect the "best" solution will be an implementation of the State (or [Strategy](http://en.wikipedia.org/wiki/Strategy_pattern)) Pattern which takes care of setting and clearing the shortcuts for you like @John mentioned, depending on what State you're in/what Strategy you want to use. – Matt Klein Sep 20 '12 at 16:15