2016-04-08 45 views
3

標準のDataGridViewImageColumnを内部に持つカスタムのDataGridViewコンポーネントを作成しました。新しいプロパティは、特定のテーブルに必要がないときにカラムの可視性を変更します。コンストラクタに列を追加し、CellFormattingイベントでそれを更新します。それは意図したように働く部分です。カスタムDataGridView列をデザイナで使用するときに重複します

コントロールを新しいフォームにドロップすると、コントロールが新しいフォームに表示されます。プログラムを実行すると、グリッド内に2つのイメージ列が表示されます。

Screenshot in designer

新しいフォーム

だけでコンポーネントを追加し、私はそれは私に2つの列を示し、何も変更せずに、それを起動するとDock.Fill

Screenshot from application running

を設定します。最初のものは正常に動作していて、2番目のものは欠けているx画像を常に表示しています(データがないのでxが両方表示されます)。

フォームのデザイナーには、自動的に追加されたイメージの列があります。

private CustomDataGridView customDataGridView1; 
private System.Windows.Forms.DataGridViewImageColumn dataGridViewImageColumn1; 

私がフォームで編集し続けると、VSが同じ列のさらに多くのコピーを作成することがあります。問題を解決するために、私はDGV.Columnsの一覧を今すぐ消去しなければなりません。

VSが自分のフィールドをコピーしないようにするにはどうすればよいですか?

次のコードは、問題を再現するための最小限の部分です。

public class CustomDataGridView : DataGridView 
{ 
    private DataGridViewImageColumn EditStatusIcons; 

    private bool hasIcons = true; 
    public bool HasIcons 
    { 
     get { return this.hasIcons; } 
     set 
     { 
      if (this.Columns["EditIcons"] == null) return; 

      this.Columns["EditIcons"].Visible = value; 
      this.hasIcons = value; 
     } 
    } 

    public CustomDataGridView() 
    { 
     this.EditStatusIcons = new System.Windows.Forms.DataGridViewImageColumn(); 

     this.EditStatusIcons.HeaderText = ""; 
     this.EditStatusIcons.Name = "EditStatusIcons"; 

     this.Columns.Add(this.EditStatusIcons); 
    } 
} 

編集:は私もCustom DataGridView adds columns everytime I buildに似this.AutoGenerateColumns = false;を使用しようとしたと述べました。何も変わりません。

フォームの列のリストを消去すると、作業列が削除され、間違った名前の完全な空の列である列dataGridViewImageColumn1が残ります。

+0

あなたはDataGridViewののデザイナーに追加どのように多くの列がありますか? – DmO

+0

なし私はフォーム上にコンポーネントをドロップし、DockスタイルをFillに設定しました。 VSは独自の列を追加しました。 – Booser

+0

コントロールが正常に動作しています。コンストラクタで列を追加した後、デザイナは列をシリアル化します。次に、アプリケーションを実行し、コンストラクターに列を追加します。だからあなたは2つの列を持っています。これはこのように続き、2列に限定されません。ビルドして実行する必要はありませんが、グリッドを含むフォームを開いてフォームに小さな変更を加えて保存すれば十分です。新しいコラムが生まれました! –

答えて

3

コントロールが正常に動作しています。

理由は、あなたはその後、設計者が列をシリアル化し、コンストラクタ内の列を追加しました。次に、アプリケーションを実行し、コンストラクターに列を追加します。だからあなたは2つの列を持っています。これはこのように続き、2列に限定されません。ビルドして実行する必要はありませんが、グリッドを含むフォームを開いてフォームに小さな変更を加えて保存すれば十分です。新しいコラムが生まれました!この問題を解決するために、あなたの要件に基づいて

ソリューション

、あなたはこれらのオプションを検討することができます

  1. チェックコントロールがデザインモードになっている場合は、列を追加しないでください実行時にのみ追加してください。

  2. コントロールに既存のイメージ列が含まれているかどうかを確認して、別のイメージ列を追加しないでください。列をいくつかのプロパティのタイプによって一意にすることができます。

  3. コントロールのカスタムデザイナーを作成し、コントロールの初期化に列を追加するコードを配置できます。この方法では、フォームにコントロールを追加するときにのみコードが実行されます。


ソリューションの間で選択するソリューション

に関するいくつかの注意事項は、完全にあなたの要件に基づいて、すべてのオプションが利用可能です。しかし、ソリューションに関するこれらの注意事項を検討:それはコンストラクタで動作しないので、第一ソリューションについて

  1. を、DesignModeプロパティを使用しないでください。例えば、それはタイプMyCustomImageColumnの列の新しいMyCustomImageColumnタイプのみチェック存在を追加するには十分だし、それが存在する場合は、別のものを追加しない、第二ソリューションについて

    if (System.ComponentModel.LicenseManager.UsageMode != LicenseUsageMode.Designtime) 
    { 
        //The control is not in design mode, add the column here. 
    } 
    
  2. :代わりにこの方法をチェックし実行しますそれらのうちの1つで十分です。

  3. 第3の解決策について。少なくとも現在のところ、私はそれに従うことをお勧めしません前の簡単なソリューションの両方を使用することができます。 DataGridViewには独自のデザイナー名DataGridViewDesignerが含まれています。これは内部的なもので、継承することはできません。この要件のためにデザイナーを作成するだけの場合は、元のデザイナーの一部の機能が欠落します。おそらくあなたはこれを回避することができ、デザイナーの代わりにToolBoxItemを作成することもできますが、必要はありません。このような場合の将来の読者にとって、答えをより完全かつ有用にするためのオプションがここにあります。
+0

私は最初のものを試しました。 'if(!DesignMode)'は列の作成と追加を中心にしていますが、デザイナーにはとにかくあります。または何か間違っているのですか? 2番目の方法は私が前にやっていたものでした。私はそこに右の列がないときに私の財産のセッターに列を作成しましたが、それは非常に有用ではなかったので、私はどの列がそこになければならないか見つけることができませんでした。私は異なるイメージの列に2つのプロパティを使用しています。私はカスタムデザイナーのソリューションについて少しお読みになります。 – Booser

+0

新しい列の作成には、正確に何が起こったのかわかりませんでしたが、フォーム上で作業した後、フォームに約40列ありました。@ – Booser

+0

理由はまさに私です前記。ビルドして実行する必要はありませんが、グリッドを含むフォームを開いてフォームに小さな変更を加えて保存すれば十分です。新しいコラムが生まれました! –

1

人々は何年もこの問題と戦ってきたが、としてレザが、この予想される動作を述べた - ので、それは「固定」ではありませんでしだ理由。この問題については、長らくMSDN forum threadが議論されています。数多くの失敗したソリューション提案の中で、Rezaによって提供された成功した提案のほとんどは、ある程度示唆されています。上記スレッドで

、第CoolDadTxユーザによって提案された第四の提案がUserControlDataGridViewをラップし、次いでカラムにその方法を追加することです。さらに推論:

継承を使用してプロパティを設定するためには悪い習慣である、 継承は、機能を追加したり、現在の一方の 挙動をオーバーライドするために使用されるべきです。

このようなカスタマイズを行う場合は、代わりに usercontrolを使用するか、実行時に gridviewpropertyをコンフィグレーションする共有関数を使用する必要があります。

- マルコ・ギニャール、2014年7月17日

利点はUserControlあなただけが明示的に公開しましたデザイナーにプロパティを追加することです。したがって、追加された列は複製されません。それはDesignTime if文のように簡潔ではありませんが、使い方は次のようになります。

public class CustomControl : UserControl 
{ 
    private DataGridViewImageColumn EditStatusIcons; 
    public DataGridView DGV; 

    private bool hasIcons = true; 
    public bool HasIcons 
    { 
     get { return this.hasIcons; } 
     set 
     { 
      if (this.DGV.Columns["EditStatusIcons"] == null) return; 

      this.dataGridView1.Columns["EditStatusIcons"].Visible = value; 
      this.hasIcons = value; 
     } 
    } 

    public CustomDataGridView() 
    { 
     this.EditStatusIcons = new System.Windows.Forms.DataGridViewImageColumn(); 

     this.EditStatusIcons.HeaderText = ""; 
     this.EditStatusIcons.Name = "EditStatusIcons"; 

     this.DGV= new DataGridView(); 
     this.DGV.Dock = DockStyle.Fill; 
     this.DGV.Columns.Add(this.EditStatusIcons); 

     this.Controls.Add(this.DGV); 
    } 
} 
+1

**•**解決方法は要件によって異なります。現在の質問では、継承を使用してプロパティをランタイム専用のプロパティにすることを好みます。 **•**ユーザーコントロールソリューションは、多くの状況にも適していますが、これにはいくつかの問題があります。これはデザイナーでホストされたコントロールで作業する能力を失うためです。 –

+0

** **ランタイム専用のプロパティを必要としない場合は、オリジナルのデザイナーを見逃さない場合はカスタム 'Designer'を作成し、' InitializeNewComponent'をオーバーライドするか、カスタム 'ToolBox'アイテムを作成し、' CreateComponentsCore'をオーバーライドします。 –

+0

デザイナーのホストされたコントロールについての素晴らしい点。 2番目のコメントはおそらく同様に有用ですが、私はそれを深く理解するために勉強しなければなりません。 – OhBeWise

関連する問題