none
DataGridViewのReadOnlyのセルのフォーカスを遷移させない処理とCellValidatingイベントについて RRS feed

  • 質問

  • はじめまして

    C#のWindouwsアプリを開発しています。
    件名に関してどなたかご教授お願いします。

    事前の情報としまして、
    DataGridViewのフォーカス遷移時にReadOnlyがtrueのセルには
    カーソル遷移をさせたくなく、下記のサイトを参考にDataGridView
    をカスタマイズしました。
    http://social.msdn.microsoft.com/Forums/ja-JP/vbexpressja/thread/fc1a0d8d-23d1-4a4e-a88c-f9a1edd81cff

    問題なく、動作しているのですが、
    DataGridViewのCellValidatingイベントで、
    各セルのエラーチェックを行っており、
    入力した内容がエラーだった場合は、「e.Cancel = true」
    を使用し、セルの移動をキャンセルさせています。


    ここで、問題が発生しています。
    カスタマイズしたDataGridViewでは、フォーカスを移動させて
    いるのにもかかわらず、CellValidatingイベントでは、
    セルの移動をキャンセルしているため、
    カスタマイズしたDataGridViewで
    「セル値の変更をコミットまたは中止できないため、操作は成功しませんでした。」
    とエラーが発生してしまいます。


    何か良い解決方法はありませんでしょうか??
    よろしくお願いします。

    • 移動 山本春海 2011年5月9日 2:07 適切なカテゴリに移動しました (移動元:Visual Basic Express Edition)
    2011年5月2日 9:45

回答

  • CurrentCellが移動する時にCellValidatingイベントが発生するので、必要のない時にはCellValidatingイベントが発生しないようにしてみました。suppressCellValidatingというフラグを追加して制御しています。

       public class DataGridViewEx : DataGridView
       {
         //直前に押したキーがEnterならtrue
         bool isEnterLast = false;
    
         bool suppressCellValidating = false;
    
         [System.Security.Permissions.UIPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Window = System.Security.Permissions.UIPermissionWindow.AllWindows)]
         protected override bool ProcessDialogKey(Keys keyData)
         {
    
            try
            {
              isEnterLast = false;
              suppressCellValidating = false;
    
              //Enterキーが押された時は、Tabキーが押されたようにする
              if ((keyData & Keys.KeyCode) == Keys.Enter)
              {
                 isEnterLast = true;
                 DataGridViewCell _CurrentCell = this.CurrentCell;
    
                 int col = this.CurrentCell.ColumnIndex + 1;
                 while (col < this.Columns.Count)
                 {
                   if (this.Columns[col].ReadOnly == false)
                   {
                      break;
                   }
                   col = col + 1;
                 }
    
                 if (col < this.Columns.Count)
                 {
                   //現在の行
                   this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
                 }
                 else
                 {
                   if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                   {
                      for (col = 0; col < this.Columns.Count - 1; col++)
                      {
                        if (this.Columns[col].ReadOnly == false)
                        {
                           break;
                        }
    
                      }
                      this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                   }
                 }
    
                 if (this.cellValidatingCancel)
                 {
                   suppressCellValidating = true;
                   this.CurrentCell = _CurrentCell;
                   BeginEdit(false);
                   this.NotifyCurrentCellDirty(true);
                 }
    
                 return true;
              }
              return base.ProcessDialogKey(keyData);
            }
            catch (Exception ex)
            {
              throw ex;
            }
    
    
         }
    
         [System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
         protected override bool ProcessDataGridViewKey(KeyEventArgs e)
         {
            isEnterLast = false;
            suppressCellValidating = false;
    
            try
            {
              //Enterキーが押された時は、Tabキーが押されたようにする
              if (e.KeyCode == Keys.Enter)
              {
                 isEnterLast = true;
                 DataGridViewCell _CurrentCell = this.CurrentCell;
    
                 int col = this.CurrentCell.ColumnIndex + 1;
                 while (col < this.Columns.Count)
                 {
                   if (this.Columns[col].ReadOnly == false)
                   {
                      break;
                   }
                   col = col + 1;
                 }
    
                 if (col < this.Columns.Count)
                 {
                   //現在の行
                   this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
                 }
                 else
                 {
                   if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                   {
                      for (col = 0; col < this.Columns.Count - 1; col++)
                      {
                        if (this.Columns[col].ReadOnly == false)
                        {
                           break;
                        }
    
                      }
                      this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                   }
                 }
    
                 if (this.cellValidatingCancel)
                 {
                   suppressCellValidating = true;
                   this.CurrentCell = _CurrentCell;
                   BeginEdit(false);
                   this.NotifyCurrentCellDirty(true);
                 }
    
                 return true;
              }
              return base.ProcessDataGridViewKey(e);
            }
            catch (Exception ex)
            {
              throw ex;
            }
    
    
         }
    
    
         bool cellValidatingCancel = false;
    
         protected override void OnCellValidating(DataGridViewCellValidatingEventArgs e)
         {
            if (suppressCellValidating)
              return;
            
            base.OnCellValidating(e);
    
            cellValidatingCancel = e.Cancel;
    
            if (isEnterLast)
              e.Cancel = false;
         }
    
       }
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク Ninichi 2011年5月6日 9:33
    2011年5月6日 7:25
    モデレータ

すべての返信

  • 実際に簡単なコードを書いて試してみましたが、こちらで再現することができませんでした。再現する最低限のコードを示していただけませんでしょうか?

    # C#と書かれていますが、こちらはVBのフォーラムになります。モデレーターの方がC#の方へこのスレッドを移動して下さると思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年5月4日 0:39
    モデレータ
  • ご回答ありがとうございます。

    簡単ではありますが、ソースを下記に記載します。

    ■カスタマイズしたDataGridView

    public class DataGridViewEx : DataGridView
    {
        [System.Security.Permissions.UIPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Window = System.Security.Permissions.UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogKey(Keys keyData)
        {
            try
            {
                //Enterキーが押された時は、Tabキーが押されたようにする
                if ((keyData & Keys.KeyCode) == Keys.Enter)
                {
                    int col = this.CurrentCell.ColumnIndex + 1;
                    while (col < this.Columns.Count)
                    {
                        if (this.Columns[col].ReadOnly == false)
                        {
                            break;
                        }
                        col = col + 1;
                    }

                    if (col < this.Columns.Count)
                    {
                        //現在の行
                        this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];

                    }
                    else
                    {
                        if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                        {
                            for (col = 0; col < this.Columns.Count - 1; col++)
                            {
                                if (this.Columns[col].ReadOnly == false)
                                {
                                    break;
                                }

                            }
                            this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];

                        }
                    }
                    return true;
                }
                return base.ProcessDialogKey(keyData);
            }
            catch (Exception ex)
            {
                throw ex;
            }


        }

        [System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)
        {
            try
            {
                //Enterキーが押された時は、Tabキーが押されたようにする
                if (e.KeyCode == Keys.Enter)
                {
                    int col = this.CurrentCell.ColumnIndex + 1;
                    while (col < this.Columns.Count)
                    {
                        if (this.Columns[col].ReadOnly == false)
                        {
                            break;
                        }
                        col = col + 1;
                    }

                    if (col < this.Columns.Count)
                    {
                        //現在の行
                        this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];

                    }
                    else
                    {
                        if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                        {
                            for (col = 0; col < this.Columns.Count - 1; col++)
                            {
                                if (this.Columns[col].ReadOnly == false)
                                {
                                    break;
                                }

                            }
                            this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];

                        }
                    }
                    return true;
                }
                return base.ProcessDataGridViewKey(e);
            }
            catch (Exception ex)
            {
                throw ex;
            }


        }

    }

    ■DataGridViewのイベント

    private void DataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
            {
                try
                {

                    //現在の値を取得
                    string val = string.Empty;
                    val = e.FormattedValue.ToString();
                    
                    if (e.ColumnIndex == 0)
                    {
                        //空白チェック
                        if (val == string.Empty)
                        {
                            //エラーメッセージ
                            MessageBox.Show("何か値を入力してください");
                            e.Cancel = true;
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }

            }

    簡単ではありますが、ソースです。

    よろしくお願いします。

     

    2011年5月6日 0:11
  • いくつかやり方があると思いますが、CellValidatingのオーバーライドをしてEnterキーでの動作をカスタマイズしてみました。DataGridViewExクラス内のみで完結するので、扱いやすいと思います。

      public class DataGridViewEx : DataGridView
      {
        //直前に押したキーがEnterならtrue
        bool isEnterLast = false;
    
        [System.Security.Permissions.UIPermission(
          System.Security.Permissions.SecurityAction.LinkDemand,
          Window = System.Security.Permissions.UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogKey(Keys keyData)
        {
    
          try
          {
            isEnterLast = false;
    
            //Enterキーが押された時は、Tabキーが押されたようにする
            if ((keyData & Keys.KeyCode) == Keys.Enter)
            {
              isEnterLast = true;
              DataGridViewCell _CurrentCell = this.CurrentCell;
    
              int col = this.CurrentCell.ColumnIndex + 1;
              while (col < this.Columns.Count)
              {
                if (this.Columns[col].ReadOnly == false)
                {
                  break;
                }
                col = col + 1;
              }
    
              if (col < this.Columns.Count)
              {
                //現在の行
                this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
              }
              else
              {
                if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                {
                  for (col = 0; col < this.Columns.Count - 1; col++)
                  {
                    if (this.Columns[col].ReadOnly == false)
                    {
                      break;
                    }
    
                  }
                  this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                }
              }
    
              if (this.cellValidatingCancel)
              {
                this.CurrentCell = _CurrentCell;
                BeginEdit(false);
                this.NotifyCurrentCellDirty(true);
              }
    
              return true;
            }
            return base.ProcessDialogKey(keyData);
          }
          catch (Exception ex)
          {
            throw ex;
          }
    
    
        }
    
        [System.Security.Permissions.SecurityPermission(
          System.Security.Permissions.SecurityAction.LinkDemand,
          Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)
        {
          isEnterLast = false;
    
          try
          {
            //Enterキーが押された時は、Tabキーが押されたようにする
            if (e.KeyCode == Keys.Enter)
            {
              isEnterLast = true;
              DataGridViewCell _CurrentCell = this.CurrentCell;
    
              int col = this.CurrentCell.ColumnIndex + 1;
              while (col < this.Columns.Count)
              {
                if (this.Columns[col].ReadOnly == false)
                {
                  break;
                }
                col = col + 1;
              }
    
              if (col < this.Columns.Count)
              {
                //現在の行
                this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
              }
              else
              {
                if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                {
                  for (col = 0; col < this.Columns.Count - 1; col++)
                  {
                    if (this.Columns[col].ReadOnly == false)
                    {
                      break;
                    }
    
                  }
                  this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                }
              }
    
              if (this.cellValidatingCancel)
              {
                this.CurrentCell = _CurrentCell;
                BeginEdit(false);
                this.NotifyCurrentCellDirty(true);
              }
    
              return true;
            }
            return base.ProcessDataGridViewKey(e);
          }
          catch (Exception ex)
          {
            throw ex;
          }
    
    
        }
    
    
        bool cellValidatingCancel = false;
    
        protected override void OnCellValidating(DataGridViewCellValidatingEventArgs e)
        {
          base.OnCellValidating(e);
    
          cellValidatingCancel = e.Cancel;
    
          if (isEnterLast)
            e.Cancel = false;
        }
      }
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年5月6日 4:55
    モデレータ
  • ありがとうございます。

    システムエラーは回避できましたが、

    エラーメッセージが2回でてしまいます。

    デバッグした結果、1番目のセルで空白チェックのエラーメッセージが表示され、

    次のセルのエラーチェックを行いエラーメッセージを表示していました。

    フォーカスは1列目のセルにありました。

    私なりにいただいたソースを変更してみたのですが、うまく動きません。

    申し訳ありませんが、もう少し、助けていただけないでしょうか。

     

    2011年5月6日 7:01
  • CurrentCellが移動する時にCellValidatingイベントが発生するので、必要のない時にはCellValidatingイベントが発生しないようにしてみました。suppressCellValidatingというフラグを追加して制御しています。

       public class DataGridViewEx : DataGridView
       {
         //直前に押したキーがEnterならtrue
         bool isEnterLast = false;
    
         bool suppressCellValidating = false;
    
         [System.Security.Permissions.UIPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Window = System.Security.Permissions.UIPermissionWindow.AllWindows)]
         protected override bool ProcessDialogKey(Keys keyData)
         {
    
            try
            {
              isEnterLast = false;
              suppressCellValidating = false;
    
              //Enterキーが押された時は、Tabキーが押されたようにする
              if ((keyData & Keys.KeyCode) == Keys.Enter)
              {
                 isEnterLast = true;
                 DataGridViewCell _CurrentCell = this.CurrentCell;
    
                 int col = this.CurrentCell.ColumnIndex + 1;
                 while (col < this.Columns.Count)
                 {
                   if (this.Columns[col].ReadOnly == false)
                   {
                      break;
                   }
                   col = col + 1;
                 }
    
                 if (col < this.Columns.Count)
                 {
                   //現在の行
                   this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
                 }
                 else
                 {
                   if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                   {
                      for (col = 0; col < this.Columns.Count - 1; col++)
                      {
                        if (this.Columns[col].ReadOnly == false)
                        {
                           break;
                        }
    
                      }
                      this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                   }
                 }
    
                 if (this.cellValidatingCancel)
                 {
                   suppressCellValidating = true;
                   this.CurrentCell = _CurrentCell;
                   BeginEdit(false);
                   this.NotifyCurrentCellDirty(true);
                 }
    
                 return true;
              }
              return base.ProcessDialogKey(keyData);
            }
            catch (Exception ex)
            {
              throw ex;
            }
    
    
         }
    
         [System.Security.Permissions.SecurityPermission(
            System.Security.Permissions.SecurityAction.LinkDemand,
            Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
         protected override bool ProcessDataGridViewKey(KeyEventArgs e)
         {
            isEnterLast = false;
            suppressCellValidating = false;
    
            try
            {
              //Enterキーが押された時は、Tabキーが押されたようにする
              if (e.KeyCode == Keys.Enter)
              {
                 isEnterLast = true;
                 DataGridViewCell _CurrentCell = this.CurrentCell;
    
                 int col = this.CurrentCell.ColumnIndex + 1;
                 while (col < this.Columns.Count)
                 {
                   if (this.Columns[col].ReadOnly == false)
                   {
                      break;
                   }
                   col = col + 1;
                 }
    
                 if (col < this.Columns.Count)
                 {
                   //現在の行
                   this.CurrentCell = this.Rows[this.CurrentCell.RowIndex].Cells[col];
    
                 }
                 else
                 {
                   if (this.CurrentCell.RowIndex != this.Rows.Count - 1)
                   {
                      for (col = 0; col < this.Columns.Count - 1; col++)
                      {
                        if (this.Columns[col].ReadOnly == false)
                        {
                           break;
                        }
    
                      }
                      this.CurrentCell = this.Rows[this.CurrentCell.RowIndex + 1].Cells[col];
    
                   }
                 }
    
                 if (this.cellValidatingCancel)
                 {
                   suppressCellValidating = true;
                   this.CurrentCell = _CurrentCell;
                   BeginEdit(false);
                   this.NotifyCurrentCellDirty(true);
                 }
    
                 return true;
              }
              return base.ProcessDataGridViewKey(e);
            }
            catch (Exception ex)
            {
              throw ex;
            }
    
    
         }
    
    
         bool cellValidatingCancel = false;
    
         protected override void OnCellValidating(DataGridViewCellValidatingEventArgs e)
         {
            if (suppressCellValidating)
              return;
            
            base.OnCellValidating(e);
    
            cellValidatingCancel = e.Cancel;
    
            if (isEnterLast)
              e.Cancel = false;
         }
    
       }
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク Ninichi 2011年5月6日 9:33
    2011年5月6日 7:25
    モデレータ
  • ありがとうございます。

    理想の動きができました。

    これからもよろしくお願いします。

    2011年5月6日 9:33