locked
標準のDataGridで、Enterによる横移動を行う方法 RRS feed

  • 質問

  • こんにちは。


    標準のDataGridでEnterによるセルの横移動が、簡単に実装できないかと探っています。
    しかし、簡単にENTERをTABに変えるような方法は見つかっていません。

    今までのところ

    1)押されたキーコードを変えてしまう方法
     見つけられなかった。

    2)カレントセルの位置をコントロールする方法
     DataGridのKeyUpイベントでカレントセルの位置から計算して新しい位置を指定する方法
     この方法は簡単ですが、既にフォーカスが移動しているため、一瞬選択状態が移動する事になり、見た目に問題があります。
     (ただし、セルの編集開始状態をコントロールしなければならない。)

    3)DataGridTemplateColumn に配置したコントロールでイベントを拾って処理
     配置したTextBoxでイベントを拾いなんとかできないかなと模索
     EnterのKeyUpイベントを拾わないので断念
     TABは拾うのですが…

    という感じです。


    また、ENTERでの移動は、ENTERの意味が「編集確定」?のせいか、編集状態が維持されないので、ENTERキーそのものでの移動に意味があるのか?という疑問は残るのですが・・・編集状態の制御も別途実装しないとだめみたいですし。


    結局、ENTERキーとTABキーの入力をすり替える方法が無ければ、簡単にENTERでの横移動を実現できないと思うのです。
    3rdParty製品やDataGrid(もどき)を0から実装すると可能な事は解っていますが、標準のDataGrid でENTERキーによる横移動を実装する方法はあるのでしょうか?


    K.Oumi
    2010年3月18日 1:37

回答

  • 標準のDataGridで、という前提なので微妙ですが
    自前でDataGridを継承したCustomDataGridを定義して
    OnKeyDownをオーバーライドしてEnterKeyが押された時に処理を乗っとるようにすれば
    2)の方法での見た目の問題は回避できるような気がします。

    最後の列でEnter押した時に次の行、とかいう動きまで自力で再現する必要がありますけど…

    参考までにコードです
        public class CustomDataGrid : DataGrid
        {
    
            public CustomDataGrid() : base()
            {
            }
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    this.MoveNextCell();
                    e.Handled = true;
                };
    
                base.OnKeyDown(e);
            }
    
            private void MoveNextCell()
            {
    
                DataGridColumn currentcol = this.CurrentColumn;
                
                // 現在のカラムが最大かどうか
                bool isLastCol = (currentcol.DisplayIndex == this.Columns.Count - 1); 
    
                if (!isLastCol)
                {
                    // 編集を終了して次へ
                    this.CommitEdit();
                    this.CurrentColumn = this.Columns[currentcol.DisplayIndex + 1];
                    this.BeginEdit();
                };
    
            }
    
        }

    • 編集済み nk9k 2010年3月18日 5:58 サンプルコード追記
    • 回答としてマーク K.Oumi 2010年3月18日 7:14
    2010年3月18日 5:52

すべての返信

  • 標準のDataGridで、という前提なので微妙ですが
    自前でDataGridを継承したCustomDataGridを定義して
    OnKeyDownをオーバーライドしてEnterKeyが押された時に処理を乗っとるようにすれば
    2)の方法での見た目の問題は回避できるような気がします。

    最後の列でEnter押した時に次の行、とかいう動きまで自力で再現する必要がありますけど…

    参考までにコードです
        public class CustomDataGrid : DataGrid
        {
    
            public CustomDataGrid() : base()
            {
            }
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    this.MoveNextCell();
                    e.Handled = true;
                };
    
                base.OnKeyDown(e);
            }
    
            private void MoveNextCell()
            {
    
                DataGridColumn currentcol = this.CurrentColumn;
                
                // 現在のカラムが最大かどうか
                bool isLastCol = (currentcol.DisplayIndex == this.Columns.Count - 1); 
    
                if (!isLastCol)
                {
                    // 編集を終了して次へ
                    this.CommitEdit();
                    this.CurrentColumn = this.Columns[currentcol.DisplayIndex + 1];
                    this.BeginEdit();
                };
    
            }
    
        }

    • 編集済み nk9k 2010年3月18日 5:58 サンプルコード追記
    • 回答としてマーク K.Oumi 2010年3月18日 7:14
    2010年3月18日 5:52
  • nk9k さん ありがとうございます。

    でもなぁ、これと同じ事やってうまくいかなかったんだよなぁ(TT) なんて、良く見ると

    e.Handled = true;

    ぐは・・・・
    やられた orz

    MSDNより・・・KeyEventArgs Hendled プロパティ
    ルーティング イベントを処理済みとマークし、イベント ルート上の他のハンドラーによって、同じイベントが繰り返し処理されるのを防ぐかどうかを示す値を取得または設定します。

    これってそういう意味だったのか・・・
    結局、継承して作ったって、KeyDownイベントでフォーカス移動するのはかわんないんだ。なんでかわからんけどしょうがない・・・なんて諦めていたのですが。
    うわー、これが無かったせいで自分のカスタムコントロールは、だめだったんだ(TT)


    助かりました。ありがとうございます。



    ちなみに、さくっと動いたもので「えー!」と慌てて MoveNextCellメソッドを本気でMSDNで探したという・・・(^^;なんというお馬鹿。

    DataGridのKeyDownイベントの説明も
    継承元へのメモ : OnKeyDown をオーバーライドする場合は、Handledtrue に設定すると、登録されているデリゲートがイベントを受け取らないようにできます。 ルーティング イベントと KeyDown プロパティの詳細については、「Silverlight のイベントの概要」を参照してください。
    う~ん読んだつもりだったのに、全然気がつかなかった・・・なんだかなぁ・・・


    K.Oumi
    2010年3月18日 7:14