« 独自のプロパティエディタ作成(ダイアログボックス形式) | トップページ | 自作コントロールを使い易くする(アイコン指定) »

2010年9月27日 (月)

独自のプロパティエディタ作成(ドロップダウン形式)

前回からの続きで、今度はドロップダウン形式のプロパティエディタを作成してみる事にする。
これもまた前回同様、CurrencyTextBox クラスを使用し、FileAttributes の列挙体型を持つ同名プロパティを追加して、これにドロップダウン形式の独自プロパティエディタを作成してみる。
なぜ金額入力用の TextBox に FileAttributes プロパティが必要なのか?と突っ込みたくなるかもしれないが、そこは勘弁願いたい。

では、さっそく CurrencyTextBox クラスに、 FileAttributes プロパティを追加する。

using System.IO;
...
private FileAttributes fileAttributes = FileAttributes.Archive;
public FileAttributes FileAttributes
{
    get
    {
        return fileAttributes;
    }
    set
    {
        fileAttributes = value;
    }
}

これでコンパイルすれば、フォームに貼り付けられた CurrencyTextBox のプロパティに、FileAttributes プロパティが追加されているのが確認出来る。

プロパティウィンドウでは、列挙体だと認識し、ドロップダウンボタンを表示している。しかし実際にこれをドロップダウンすると、

この様に FileAttributes の列挙値を項目に持つドロップダウンリストが表示され、どれか1つを選択出来る。しかし、どれか1つだけしか選択出来ない。FileAttributes は Flags列挙体であり、列挙値を複数持つ指定が可能である。設計時にこれを指定出来ないのは物足りない。Flags 列挙体型のプロパティを作成すると、このような不満が出てくる。

そこで独自プロパティエディタの作成を行ってみる。

前回の「独自のプロパティエディタ作成(ダイアログボックス形式)」で触れた様に、ドロップダウン形式の画面定義はユーザーコントロールを使用する必要がある。

実際の画面定義は、右図で示した。ユーザーコントロールという事もあり、設計時の画面表示状態のハードコピーで示している。なお、見ての通り、実質未使用の FileAttributes.Device は含めなかった。またドロップダウン形式では、閉じる系の画面定義がないのが一般的なのかもしれないが、ここはあえて付けている。理由は、ドロップダウンを意図的に閉じる場合のコードを、サンプルとしてつけておきたいからだ。

このユーザーコントロールのクラス名を FileAttributesEditorControl として、まずは前回同様、編集値をやりとりするためのプロパティ定義を行う。

private FileAttributes fileAttributes;  // プロパティ値格納用変数
public FileAttributes FileAttributes
{
    get
    {
        return fileAttributes;
    }
    set
    {
        fileAttributes = value;
        chkReadOnly.Checked          = ((value & FileAttributes.ReadOnly) != 0);
        chkHidden.Checked            = ((value & FileAttributes.Hidden) != 0);
        chkSystem.Checked            = ((value & FileAttributes.System) != 0);
        chkDirectory.Checked         = ((value & FileAttributes.Directory) != 0);
        chkArchive.Checked           = ((value & FileAttributes.Archive) != 0);
        chkNormal.Checked            = ((value & FileAttributes.Normal) != 0);
        chkTemporary.Checked         = ((value & FileAttributes.Temporary) != 0);
        chkSparseFile.Checked        = ((value & FileAttributes.SparseFile) != 0);
        chkReparsePoint.Checked      = ((value & FileAttributes.ReparsePoint) != 0);
        chkCompressed.Checked        = ((value & FileAttributes.Compressed) != 0);
        chkOffline.Checked           = ((value & FileAttributes.Offline) != 0);
        chkNotContentIndexed.Checked = ((value & FileAttributes.NotContentIndexed) != 0);
        chkEncrypted.Checked         = ((value & FileAttributes.Encrypted) != 0);
    }
}

set アクセサでは、各チェックボックスのチェック状態を設定する必要があるので、この様な記述としている。仕事でやる様なプログラミングだと、コーディング規約で禁止しているかもしれない記述であるが、全て if 文を使用しての記述だと面倒だし、これだけ数があるとかえって見難いとも思えるので、許して欲しい。

さて、ユーザーコントロール自身が、ドロップダウンを閉じる等の制御を行うには、呼び出し側から IWindowsFormsEditorService のインスタンスも受け取る必要がある。編集前の FileAttributes プロパティ値と合わせて、2つのパラメータを受け取る必要があるので、これをコンストラクタで受け取るようにした。

private IWindowsFormsEditorService editorService = null;
public FileAttributesEditorControl(FileAttributes fileAttributes,
    IWindowsFormsEditorService editorService) : this()
{
    // チェックボックスへの内容反映を行う為、プロパティに対して設定する
    this.FileAttributes = fileAttributes;
    this.editorService = editorService;
    lblClose.Visible = (editorService != null); // 「閉じる」ラベルの表示有無を決定
}

そして「閉じる」ラベルの Click イベント処理で、

private void CloseClick(object sender, System.EventArgs e)
{
    editorService.CloseDropDown();
}

と記述すれば、「閉じる」のラベル部分でクリックすれば、ドロップダウンが閉じる様になる。
あとは、各チェックボックスのチェック状態が変化したときに FileAttribute プロパティにその値を反映する必要もあるが、ここはプロパティエディタ特有の部分でもないので省略する。必要であれば、最後にあるサンプルプロジェクト一式をダウンロードして見て頂きたい。
以上で、FileAttributesEditorControl クラスの定義は終わりである。

次に、このドロップダウン形式の画面と、プロパティウィンドウの橋渡し役となる、FileAttributesEditor クラスを定義する。これも、前回同様、UITypeEditor から継承し、GetEditStyle メソッドと、EditValue メソッドをオーバーライドする。内容も前回に似ているので、コメントを読むだけで、問題なく理解出来ると思う。

internal class FileAttributesEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        // プロパティエディタとして、ドロップダウン ダイアログを使用する事を通知
        return UITypeEditorEditStyle.DropDown;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService editorService = null;

        // MSDN UI 型エディターの実装 に基づいた記述
        if (provider != null)
        {
            editorService =
                provider.GetService(
                typeof(IWindowsFormsEditorService))
                as IWindowsFormsEditorService;
        }

        // MSDN UI 型エディターの実装 に基づいた記述
        if (editorService == null)
        {
            return value;
        }

        // FileAttributesEditorControl を使用したプロパティエディタの表示
        // コンストラクタで、現在のプロパティ値と IWindowsFormsEditorService の
        // インスタンス(editorService)を渡している。
        using (FileAttributesEditorControl fec =
                   new FileAttributesEditorControl((FileAttributes)value, editorService))
        {
            editorService.DropDownControl(fec);     // エディタ画面をドロップダウンして表示
            return fec.FileAttributes;              // 新しい設定値をプロパティ値として返す
        }
    }
}

最後に、今定義したエディタを使用するプロパティの部分に、ここで定義したエディタクラスを指定する。ここでは、CurrencyTextBoxクラスの FileAttributes プロパティに、赤字の部分を追加すれば良い。

private FileAttributes fileAttributes = FileAttributes.Archive;
[Editor(typeof(Acha_ya.SampleEditor.FileAttributesEditor),
    typeof(System.Drawing.Design.UITypeEditor))]
public FileAttributes FileAttributes
{
    get
    {
        return fileAttributes;
    }
    set
    {
        fileAttributes = value;
    }
}

以上で、全ての定義が完了である。コンパイル後、FileAttributes プロパティのエディタを開いた画面は以下の様になる。

これでドロップダウン形式のエディタ作成は終了となる。最後に、ここまでで使用したサンプルクラス定義+プロパティエディタ定義及びそのテストAPのプロジェクト一式を、CAB形式でまとめてアップしておきます。

「Sample.cab」をダウンロード

« 独自のプロパティエディタ作成(ダイアログボックス形式) | トップページ | 自作コントロールを使い易くする(アイコン指定) »

C# Tips」カテゴリの記事

コメント

UITypeEditorを実装していましたが、ここの情報がやりたいことの参考になりました!結構調べたんですが、一番分かりやすかったです。ありがとうございました。

お役に立ててよかったです。

最近ブログを更新してないですが、励みになります。

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 独自のプロパティエディタ作成(ドロップダウン形式):

« 独自のプロパティエディタ作成(ダイアログボックス形式) | トップページ | 自作コントロールを使い易くする(アイコン指定) »