5

私は現在、編集メインメニューのキーボードショートカットとして Ctrl+C と Ctrl+V がバインドされた C# winforms アプリを持っています。リストビューでの行のコピーと貼り付けなど、これらのメニュー項目に応答するコード内のカスタム コピー/貼り付け動作があります。

ただし、私の問題は、行内のテキストを編集できることです。その場合、Ctrl + CとCtrl + Vで編集メニューコマンドをトリガーせず、デフォルトで通常のテキストベースのコピー/貼り付けを行う必要があります。

私が試したことの 1 つは、BeforeLabelEdit および AfterLabelEdit イベントをトリガーし、そこからメニュー項目を手動で無効化/再有効化することです。残念ながら、無効なメニュー アイテムのキーボード ショートカットは、メニュー アイテムの有効/無効を決定するために現在使用されている menu_Popup イベントを引き続きトリガーするようです。(たとえば、「貼り付け」は、クリップボードにテキストがある場合にのみアクティブになります)。そのため、メニュー項目を無効にしても、キーボード ショートカットは引き続き Popup イベントをアクティブにし、メニュー項目を再度有効にします。(これはバグですか?)

古いショートカットを手動で保存せずにメニュー項目のキーボードショートカットを一時的に無効にし、ショートカットをnullに設定し、再度有効にする必要があるときにそれをコピーして戻す方法が見つかりません(これは汚いと感じます)。

確かに、コピー/貼り付けの動作をオーバーライドしたり、追加したりすることは、一般的にやりたいことですか? ここで使用するより良いパターンはありますか?

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()実際の状態 (または戦略) パターンになるには、単に if/else またはスイッチを使用するのでDoPaste()はなく、実装する個別の具象クラスが必要です。次に、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();
        }
    }
}

ご覧のとおり、状態が 2 つしかない場合、これは少しやり過ぎかもしれません (そして、状態の数はおそらく増加しません)。

于 2012-09-18T19:44:57.283 に答える