none
DataGridViewColumn の columnName としてフィールド名を自動的に割り当てるには RRS feed

  • 質問

  • id, name というフィールドをもつ DataTable をデータ ソースからフォームに
    ドラッグして生成される DataGridView の「列の編集」を以下に示します。


    図 (1)


     

    左側「選択された列」の "name" を選択すると、
    右側「バインド列のプロパティ」の (Name) が "dataGridViewTextBoxColumn2" になっています。


    このままでは、


      this.dataGridView1.Rows[0].Cells["name"].Value


    として "name" セルにアクセスした場合、以下のようなエラーを出してしまいます。


    図 (2)

     

     

    これはメッセージ通り、DataGridViewColumn の columnName として "name"
    をもつ列がないからです (下記リスト(1) 参照)


    リスト (1) DataGridViewCellCollection のインデクサ

    Code Snippet

    public class DataGridViewCellCollection : BaseCollection, IList
    {
      public DataGridViewCell this[string columnName]
      {
        get
        {
          DataGridViewColumn dataGridViewColumn = null;


          if (this.owner.DataGridView != null)
          {
            dataGridViewColumn = this.owner.DataGridView.Columns[columnName];
          }


          if (dataGridViewColumn == null)
          {
            throw new ArgumentException(

              SR.GetString(SR.DataGridViewColumnCollection_ColumnNotFound, columnName),

              "columnName");
          }


          return (DataGridViewCell) this.items[dataGridViewColumn.Index];
        }

     

     

    図(1) で確認できる通り、"name" に相当する列は columnName として
    "dataGridViewTextBoxColumn2" がドラッグ・ドロップ時に自動的に割り当てられています。


    この自動的に割り当てられる命名を回避して、

    DataPropertyName と同じように、フィールド名が設定される方法はないものでしょうか?

    2008年5月5日 18:32

回答

  •  custarさんこんにちは。

     Visual Studioのアドインを作り、デザイン時に一括で名前を変更する方法もあります。私はそうしています。アドインについてはVisual Studio付属のユーザーズガイドが役に立ちます。

     

    2008年5月7日 7:33
  •  custar さんからの引用
    そもそも、何故 DataPropertyName だけにフィールド名が割り当てられて、
    (column)Name には割り当てられないのか.....

     

    Name プロパティの値は、IDE が生成する Form デザイナコードのコントロール識別子と同じになるので、識別子として使用できない文字(空白など)が含まれる可能性が高い列名を、Name の値には使いたくなかったからではないでしょうかね(DataGridView としては、同じデータソース列を複数個追加することもできますし)。

    # Name の値としては、空白が含まれたり重複したりしても大丈夫ですが、もしそのようなコードを IDE が生成すれば、混乱の元になると思います。

     

    custar さんの方法がシンプルで良さそうに思いますが、次のような拡張メソッドを考えてみました。

    これを使用すると、Cells["name"].Value の箇所が Cells2("name").Value になります。

    # 三輪の牛さんの方法も良さそうですね。ただ、実行し忘れたりしそうで少しだけ心配です

     

    Code Snippet

    public static class DataGridViewRowExtensions
    {
        /// <summary>
        /// セルのコレクションから DataPropertyName が一致する
        /// セルを取得します。
        /// </summary>
        /// <param name="dataPropertyName">
        /// セルを取得する DataGridViewColumn.DataPropertyName の値。
        /// </param>
        public static DataGridViewCell Cells2(
            this DataGridViewRow row,
            string dataPropertyName)
        {
            foreach (DataGridViewColumn col in row.DataGridView.Columns)
            {
                if (string.Equals(
                        col.DataPropertyName, dataPropertyName,
                        StringComparison.OrdinalIgnoreCase))
                    return row.Cells[col.Index];
            }
            throw new ArgumentException(
                string.Format("'{0}' には '{1}' という列は見つかりません。",
                    !string.IsNullOrEmpty(row.DataGridView.Name)
                        ? row.DataGridView.Name : "(DataGridView)",
                    dataPropertyName),
                "dataPropertyName");
        }
    }

     

    2008年5月7日 8:30

すべての返信

  • こんな感じでどうでしょうか?


    Code Snippet
    private void columnsDataGridView_DataBindingComplete(
      object sender, DataGridViewBindingCompleteEventArgs e)
    {
      foreach (DataGridViewColumn col in this.columnsDataGridView.Columns)
      {
        if (col.Name != col.DataPropertyName)
        {
          col.Name = col.DataPropertyName;
        }
      }
    }

     


    binding 直後に DataPropertyName を (column)Name に代入する。


    もっといい案がありましたらお教えください。

     

     

    p.s.

    ----

    そもそも、何故 DataPropertyName だけにフィールド名が割り当てられて、

    (column)Name には割り当てられないのか.....

    2008年5月5日 19:02
  •  custarさんこんにちは。

     Visual Studioのアドインを作り、デザイン時に一括で名前を変更する方法もあります。私はそうしています。アドインについてはVisual Studio付属のユーザーズガイドが役に立ちます。

     

    2008年5月7日 7:33
  •  custar さんからの引用
    そもそも、何故 DataPropertyName だけにフィールド名が割り当てられて、
    (column)Name には割り当てられないのか.....

     

    Name プロパティの値は、IDE が生成する Form デザイナコードのコントロール識別子と同じになるので、識別子として使用できない文字(空白など)が含まれる可能性が高い列名を、Name の値には使いたくなかったからではないでしょうかね(DataGridView としては、同じデータソース列を複数個追加することもできますし)。

    # Name の値としては、空白が含まれたり重複したりしても大丈夫ですが、もしそのようなコードを IDE が生成すれば、混乱の元になると思います。

     

    custar さんの方法がシンプルで良さそうに思いますが、次のような拡張メソッドを考えてみました。

    これを使用すると、Cells["name"].Value の箇所が Cells2("name").Value になります。

    # 三輪の牛さんの方法も良さそうですね。ただ、実行し忘れたりしそうで少しだけ心配です

     

    Code Snippet

    public static class DataGridViewRowExtensions
    {
        /// <summary>
        /// セルのコレクションから DataPropertyName が一致する
        /// セルを取得します。
        /// </summary>
        /// <param name="dataPropertyName">
        /// セルを取得する DataGridViewColumn.DataPropertyName の値。
        /// </param>
        public static DataGridViewCell Cells2(
            this DataGridViewRow row,
            string dataPropertyName)
        {
            foreach (DataGridViewColumn col in row.DataGridView.Columns)
            {
                if (string.Equals(
                        col.DataPropertyName, dataPropertyName,
                        StringComparison.OrdinalIgnoreCase))
                    return row.Cells[col.Index];
            }
            throw new ArgumentException(
                string.Format("'{0}' には '{1}' という列は見つかりません。",
                    !string.IsNullOrEmpty(row.DataGridView.Name)
                        ? row.DataGridView.Name : "(DataGridView)",
                    dataPropertyName),
                "dataPropertyName");
        }
    }

     

    2008年5月7日 8:30
  • 三輪の牛 さん、情報ありがとうございます。

     

     三輪の牛 さんからの引用

    アドインについては Visual Studio 付属のユーザーズガイドが役に立ちます。


    付属って事は、購入した物に付いているのですか? 私のは試用版....


    - Visual Studio .NET 2002 必要システム および パッケージ内容

     

    2008年5月7日 9:58
  •  TH01 さんからの引用

    # Name の値としては、空白が含まれたり重複したりしても大丈夫ですが、もし
      そのようなコードを IDE が生成すれば、混乱の元になると思います。


    なるほど、万人向けにはそうですね。


    馴れて来たら自分で設定できるようにしておいて欲しかったなぁ。そういうオ
    プションがないのかな、と思いましたが、詳しい方が自作されているところを
    見ると、ないようですね。


     TH01 さんからの引用

    次のような拡張メソッドを考えてみました。これを使用すると、

    Cells ["name"].Value の箇所が
    Cells2("name").Value になります。


    これどう使うのでしょう?

     

     TH01 さんからの引用

    # 三輪の牛さんの方法も良さそうですね。ただ、実行し忘れたりしそうで少しだけ心配です


    私の印象では、これが後々楽そうなんですが。
    実行し忘れたらテストで引っ掛かるので、問題ないと思います。
    また、何らかの更新の催促を仕込めないかとも考えてしまいます。

    2008年5月7日 10:15
  •  custar さんからの引用


    Code Snippet
    private void columnsDataGridView_DataBindingComplete(
      object sender, DataGridViewBindingCompleteEventArgs e)
    {
      foreach (DataGridViewColumn col in this.columnsDataGridView.Columns)
      {
        if (col.Name != col.DataPropertyName)
        {
          col.Name = col.DataPropertyName;
        }
      }
    }

     

     

     

    私は毎回引っ掛かりそうなので、これを実装した DataGridView を継承させて
    ツールボックスに登録しておくかもしれません。

    # そんなことできるのかな?

    2008年5月7日 10:21
  • DataGridViewRowExtensions クラスをソースのどこかにコピペしておき、
    Cells["name"].Value と書く代わりに
    Cells2("name").Value と書く
    という意味でした。

     

    Cells のインデクサは Name を見ますが、Cells2 拡張メソッドは DataGridViewRowExtensions クラスでの実装の通り、DataPropertyName を調べます。
    # custar さんは Visual Studio 2008 でしたよね。

     

    ツールボックスへの登録は、ツールボックス上で右クリックしたメニューにある [アイテムの選択] でできます。

    2008年5月7日 10:53
  •  TH01 さんからの引用

    Cells["name"].Value と書く代わりに
    Cells2("name").Value と書く


    えぇぇえ!?

     

    Code Snippet


    string s1 = this.columnsDataGridView.Rows[0].Cells["name"].Value;
    string s2 = this.columnsDataGridView.Rows[0].Cells2("name").Value;

     

     

    という記述において、Rows[0]. の後に Intellisense で Cell2 が現れました。ナンデ?


     

     

     

    分からん。知らないことが起きてる!


    多分 Cell2 の第1引数に this が入っているのがトリックの種だろうと思いま
    すが、何なんですか、これ?

     

    それとも DataGridViewRow + Extensions という命名規則に何か裏があるのか....

    2008年5月7日 13:38
  •  拡張メソッドです。

     既存のクラスにメソッドを後付けできる機能です。

     アドインについてはオンラインヘルプでも同じことが書いてあります。

     Expressは使えたかどうか?

    2008年5月8日 0:41
  • 拡張メソッドのドキュメント見つけました。
    アドインはこれから。

     

    三輪の牛 さん、情報ありがとうございます。

    2008年5月8日 4:10