none
TabControl の tabPage2 以降で Visible = False にした DataGridView の Column が見えてしまう RRS feed

  • 質問

  • TabControl 上に DataGridView を表示させたフォームを作成しています。
    DataGridView には見せなくていい id 列があるので Column を Visible = False にしています。

     

    Form Designer 上では id 列はきっちり非表示になっていますが、実行させてみると、

     

    tabPage1 の DataGridView の id 列は非表示、
    tabPage2 の DataGridView の id 列は表示 (!)

     

    tabPage2 以降の DataGridView の id 列は全て表示されてしまいました。

     

    - 確認画像 : デザイナー上での表示
    - 確認画像 : 実行時の表示

     

    デザイナーで Visible = False としていますので、念のため
    Form1.Designer.cs で設定箇所を確認すると、以下のようにと正しく設定され
    ていることを確認しています。

     

    # 上記画像には "Form4" と出ていますが、ここでは "Form1" と言っておきます。

    # こちらの作業環境では、正確には Designer.cs は "Form4" のものです。

     

    コード ブロック

    //
    // dataGridViewTextBoxColumn1
    //
    this.dataGridViewTextBoxColumn1.DataPropertyName = "id";
    this.dataGridViewTextBoxColumn1.HeaderText = "id";
    this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
    this.dataGridViewTextBoxColumn1.ReadOnly = true;
    this.dataGridViewTextBoxColumn1.Visible = false;
    //
    // dataGridViewTextBoxColumn3
    //
    this.dataGridViewTextBoxColumn3.DataPropertyName = "id";
    this.dataGridViewTextBoxColumn3.HeaderText = "id";
    this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
    this.dataGridViewTextBoxColumn3.ReadOnly = true;
    this.dataGridViewTextBoxColumn3.Visible = false;

     


    DataGridView に用いたデータテーブルは以下の通りです。

     

    ひらがな50音を親子リレーションをもったテーブルとして作りました。
    columns テーブルの id は chars テーブルで column_id として使われています。

     

    コード ブロック

    columns
    ------------------------------------------------
    id      INT             NOT NULL PRIMARYKEY <-------+
    name    VARCHAR(50)     NOT NULL                    |   
    ------------------------------------------------    |
                                                        |
    chars                                               |
    ------------------------------------------------    |
    id          INT             NOT NULL PRIMARYKEY     |
    column_id   INT             NOT NULL ---------------+ FOREIGNKEY
    name        VARCHAR(50)     NOT NULL
    ------------------------------------------------

     

     

    以上のように、
    複数の TabPage をもつ TabControl において、
    2つ目以降の TabPage で
    Visible = False にした DataGridView の Column が見えてしまっています。

     

    回避法をご存知の方、いらっしゃいませんか?

     

    + 追記 (2008-01-10)

    もしかしてバグ?

    2008年1月7日 4:24

回答

  • 先ほどは良くないと書きましたけど、背景は何となく想像できます。
    そこで試しに以下のようにしてみると、直りました。
    修正すると別の弊害にもつながるので、直せないんだと思います。

     

    public Form1()
    {
          InitializeComponent();

          IntPtr h = columnsDataGridView.Handle;
    }

     

    追記:
    ある勘違いをしてることに気付きました。設計がよくないとか仕方がないとかは忘れてください。
    それなのにこのコードで改善されるということは、2ページ目移行は非表示状態なのでハンドルが作成されず、それが今回の件につながっていることには間違いないと思うんですが、それを検証する小さなプログラムを作っても再現させることができませんでした。

    2008年1月11日 2:24

すべての返信

  • 小さなテスト用のプログラムを作成してみましたが、こちらでは再現しませんでした。
    TabControl との関連を書かれていますが、試しに tabPage2 にある DataGridView を tabPage1 に移動してみると正常になるのでしょうか?
    DataGridView の AutoGenerateColumns は関係ないでしょうか?
    (表示された列は、非表示設定されている列とは別の自動的に追加された列とか)

    バインドする前に、一度明示的に DataGridView の AutoGenerateColumns を false にしてみてはどうでしょう。
    2008年1月10日 5:45
  • TH01 さん、お返事ありがとうございます。

    これもサンプルを直接見てもらった方がいいですね。以下に置きます。

    - サンプル : InvisibleDataGridViewColumn (ダウンロード), VC# 2008 Expr ja
    # 念のためウィルスチェックしてください

    ひらがな50音をテーブルにもつデータベースを使っています (syllabary.mdf)。
      Form1 .... tabPage1,2 ともに同じ DataTable (columns) を割り当てています
      Form2 .... tabPage1 は親 DataTable (columns) を、
                     tabPage2 は子 DataTable (chars) を割り当てています

    Form1 の場合、
    tabPage1 .... 非表示効いてる
    tabPage2 .... 非表示効いてない (!)

    Form2 の場合、
    tabPage1 .... 非表示効いてる
    tabPage2 .... 非表示効いてる

    どうも同じ DataTable を各 tabPage に割り当てると出るような ....

     TH01 さんからの引用

    試しに tabPage2 にある DataGridView を tabPage1 に移動してみると正常になるのでしょうか?


    tabPage1,2 の順序を入れ替えると、今度は
    tabPage2 .... 非表示効いてる
    tabPage1 .... 非表示効いてない

    つまり、最初の tabPage のみ非表示が効くようです。


    実際こちらで作っている別アプリケーションでは、Form2 のように、tabPage
    ごとに別の DataTable を割り当てた DataGridView を置いています。各
    DataTable はリレーションをもっています。上記 Form2 の例では tabPage2 の
    非表示行は見えませんでしたが、こちらのアプリケーションでは、何故か見え
    ています。

    簡略化して再現できない....


     TH01 さんからの引用

    DataGridView の AutoGenerateColumns は関係ないでしょうか?
    バインドする前に、一度明示的に DataGridView の AutoGenerateColumns を false にしてみてはどうでしょう。


    デバッガで見ると false になってました。

    2008年1月10日 14:43
  • 同じ DataTable を複数の tabPage に置いたのがいけない、という訳じゃない
    と思い、以下のようなものを作ってみました。

    - ダウンロード : 3つの tabPage にそれぞれ独立した DataTable を DataGridView で配置
    # 要ウィルスチェック

    結果は

      tabPage1 .... 非表示 ○
      tabPage2 .... 非表示 ×
      tabPage3 .... 非表示 ×

    - 確認画像 : tabPage2 以降で非表示列が見える

    何なのかなぁ?
    2008年1月10日 16:12
  • - Re: DataGridViewColumn.Visible=False is being ignored. - MSDN Forums

    これを参考に、非表示列を DataGridView の最後尾列に移動させたら、取り敢
    えず見えないようにできました。

    でも、根本的な解決じゃないですね。直前の投稿は、再現性ありそうですから。
    2008年1月10日 16:47
  • フィードバックに上がってました。
    Setting datagridview column visible to false on second tab control page does not work
    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=108992

     

    設計によるものだそうです。
    # 設計が良くないんだと思いますけどね

     

    そこに対処が書かれているので、そうするしかなさそうです。
    一応改善されることを確認しました。

    2008年1月11日 2:00
  • 先ほどは良くないと書きましたけど、背景は何となく想像できます。
    そこで試しに以下のようにしてみると、直りました。
    修正すると別の弊害にもつながるので、直せないんだと思います。

     

    public Form1()
    {
          InitializeComponent();

          IntPtr h = columnsDataGridView.Handle;
    }

     

    追記:
    ある勘違いをしてることに気付きました。設計がよくないとか仕方がないとかは忘れてください。
    それなのにこのコードで改善されるということは、2ページ目移行は非表示状態なのでハンドルが作成されず、それが今回の件につながっていることには間違いないと思うんですが、それを検証する小さなプログラムを作っても再現させることができませんでした。

    2008年1月11日 2:24
  • TH01 さん、サポートありがとうございます。

     

    フィードバックは初めて見ました。こんな所もあるんですね。


     

    さて、結構古い報告。そこで提示されている解決方法としては
    DataBindingComplete に合わせて明示的に visible = false にするというもの。
    # んんん、積極的になれないやり方。

     

    TH01 さんが提示されている

     

    コード ブロック

    IntPtr h = columnsDataGridView.Handle;

     

     

    では結果的に不具合解消となりましたが、内部的にはどんな効果があったので
    しょう。ハンドルを渡しているだけに見えますが。

    2008年1月11日 3:52
  • はい、泥臭いですね。
    この対処ではプログラムのメンテナンス性において不安を感じました。
    数年後の修正で、デザイナで Visible を true にしても表示されないのは何故?ってことになりそうです。

     

    「ハンドルを渡しているだけに見えますが」の件ですが、
    コントロールに対応する Windows のハンドルが生成されていない場合、ハンドルを参照すれば生成されます。
    このコードはハンドルの生成が目的です。
    Visible の状態は、たいていのコントロールでは Windows 側で管理させるようにしますので、ハンドルが生成されていない場合、設計によっては不都合が生じることになります。

    2008年1月11日 4:20
  •  TH01 さんからの引用

    「ハンドルを渡しているだけに見えますが」の件ですが、
    コントロールに対応する Windows のハンドルが生成されていない場合、
    ハンドルを参照すれば生成されます。このコードはハンドルの生成が目的です。

     

    なるほど、そういう裏事情があるのですね。

     

    大凡 (おおよそ) 分かってきたので、本件はここで閉じます。

     

    TH01 さん、長い時間サポートいただきましてありがとうございました。

    2008年1月11日 4:53