DOBON.NET DOBON.NETプログラミング掲示板過去ログ

特定の型専用のコンボボックスを作りたい

環境/言語:[Win2000、C#、.Net Framework1.1]
分類:[.NET]

はじめまして。
コンボボックスのカスタマイズでつまずいています。
解決法がわかる方がいましたら、ご教授下さい。よろしくお願いします。

■やりたいこと
 ・「特定の型」専用のコンボボックスを作りたい。
 ・フォームデザイナに配置した段階でItemsとSelectedItemが設定されて欲しい。
 ・Itemsの初期化処理はクラス内に隠蔽したい。
 ・プロパティブラウザ上からSelectedItemをドロップダウンで設定したい。
 ・利用者側はSelectedItemを「特定の型」にキャストされた状態で受け取りたい。
 ・DataSourceはあまり利用したくない。(利用しないと無理ならそれでも構わない)

■書いてみたコード
例として列挙型専用のコンボボックスを以下のように実装しました。
(専用性を増すには他にも色々やることがあると思いますが、省略します)

namespace Sample
{
    // 選択項目
    public enum DropDownItem
    {
        Item1,
        Item2,
        Item3
    }

    // DropDownItem専用のコンボボックス
    public class EnumComboBox : ComboBox
    {
        public EnumComboBox()
        {
            object[] dropDownItems = new object[]
            {
                DropDownItem.Item1,
                DropDownItem.Item2,
                DropDownItem.Item3
            };

            // Items初期化
            this.Items.AddRange(dropDownItems);
            // デザイナ配置時の初期選択項目
            this.SelectedItem = DropDownItem.Item1;
        }

        // SelectedItemをDropDownItem型で使えるように再定義
        [DefaultValue(DropDownItem.Item1), Category("Data")]
        public new DropDownItem SelectedItem
        {
            set
            {
                base.SelectedItem = value;
            }
            get
            {
                return (DropDownItem)base.SelectedItem;
            }
        }
    }
}

■問題点
 プロパティブラウザで任意のプロパティ(例えばSelectedItemやTag)を変更して
 ビルドすると、FormのInitializeComponent()に以下のコードが勝手に
 挿入されてしまい、Itemsの項目が増えてしまう。
 (変更とビルドを繰り返すとItemsが増え続ける)

  this.enumComboBox1.Items.AddRange(new object[] {
      Sample.DropDownItem.Item1,
      Sample.DropDownItem.Item2,
      Sample.DropDownItem.Item3});

■他に試したこと
 ・プロパティブラウザでドロップダウン表示可能なTypeConverterを実装した
  自前のクラスを列挙型の代わりに使った場合、自前のクラスに[Serializable]を
  指定しなければ問題点のコードは挿入されないが、ビルドするたびに
  SelectedItemが初期値に戻ってしまう。(当たり前ですね…)
  [Serializable]を指定すると列挙型と同じ問題が発生する。
 ・Itemsを初期化しないでDataSource、DisplayMember、ValueMembarの設定で
  実現しようとしたが、プロパティブラウザでSelectedItemをドロップダウンで
  選択できなかった。
> ■問題点
>  プロパティブラウザで任意のプロパティ(例えばSelectedItemやTag)を変更して
>  ビルドすると、FormのInitializeComponent()に以下のコードが勝手に
>  挿入されてしまい、Itemsの項目が増えてしまう。
>  (変更とビルドを繰り返すとItemsが増え続ける)
>
> this.enumComboBox1.Items.AddRange(new object[] {
> Sample.DropDownItem.Item1,
> Sample.DropDownItem.Item2,
> Sample.DropDownItem.Item3});

InitializeComponentに初期化コードを追加したくないプロパティに
DesignerSerializationVisibilityAttributeを付加するといいと思います。
今回はItemsプロパティになると思います。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemcomponentmodeldesignerserializationvisibilityattributeclasstopic.asp
> InitializeComponentに初期化コードを追加したくないプロパティに
> DesignerSerializationVisibilityAttributeを付加するといいと思います。
> 今回はItemsプロパティになると思います。

なるほど。デザイン時にシリアル化するかどうかを制御できるんですね。
以下のコードを追加して解決することができました。

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ComboBox.ObjectCollection Items
{
    get
    {
        return base.Items;
    }
}

どうもありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板