し上を行く PropertyGrid (フォルダ選択)を表示したい,の巻
2004/04/21 新規

PropertyGrid は、使い方を理解すればするほど 便利なGUI を提供してくれるクラスです。 たとえば列挙体を持っているクラスを表示対象にすれば、ユーザ見えのプロパティではコンボ・ボックスが表示されます。 また、以下のような感じでEditor 属性を設定したstring であれば、ファイル選択ダイアログを表示してくれもします。

private string inputFilename;
[Editor(typeof(FileNameEditor),typeof(UITypeEditor))]
public string InputFilename
{
  get
  {
    return inputFilename;
  }
  set
  {
    inputFilename=value;
  }
}
非常に便利です。

こんな簡単便利にファイル選択できるなら、同じようにフォルダも選択したくなるのが当然の流れ。 「FileNameEditor クラスがあるのならFolderNameEditor クラスがあっても変じゃないはず」と考えた人は、惜しい線まで行ってます。
実際FileNameEditor クラスと同様に、FolderNameEditor クラスもSystem.Windows.Forms.Design 名前空間に存在しています。 が、残念&不可解なことに、FolderNameEditor クラスは現在このような位置付けです。
この型は、.NET Framework インフラストラクチャのサポートを目的としています。 独自に作成したコード内で直接使用することはできません。

なんだかMicrosoft は、とてもケチくさいことを言ってます。 そもそも、フォルダ選択ダイアログ(FolderBrowserDialog クラス)がユーザに提供されたのも.NET Framework 1.1 になってからでした。

ちなみにFolderNameEditor クラスは「直接使用することはできません」と言われていますが、無視して使うコトもできます。 それで良い人は今回の小技は おしまい、我が道を行ってください。

 

どうやってフォルダ選択ダイアログを表示させるか? その答えは明確で、独自のEditor クラスを実装すれば良いのです。 具体的にはUITypeEditor クラスを親クラスに持つクラスを作成します。
動作に必要なメソッドは2つです。 EditValue() メソッドでユーザ入力を処理し、GetEditStyle() メソッドでエディタのスタイル(モーダルやドロップ・ダウン等)をプロパティ・グリッドへ通知します。

ImageTrimmerを作成したときに用いたコードを、サンプルとして以下に示します。 このコードをそっくりコピーすれば、ほぼ期待する動作が得られるはずです。 プロパティに対するEditor 属性の設定方法については、FileNameEditor での設定例を参考にしてください。
ソース

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing.Design;

namespace Musi_chan.Tools.ImageTrimmer.Design
{
  public class MyFolderNameEditor : UITypeEditor
  {
    /* ******************************************************* **** *** ** *
      フィールド
    * ** *** **** ******************************************************* */
    private FolderBrowserDialog folderBrowser;

    /* ******************************************************* **** *** ** *
      コンストラクタ
    * ** *** **** ******************************************************* */
    public MyFolderNameEditor() : base()
    {
      // do nothing.
    }

    /* ******************************************************* **** *** ** *
      メソッド
    * ** *** **** ******************************************************* */
    public override object EditValue(ITypeDescriptorContext context
      ,IServiceProvider provider,object value)
    {
      // インスタンスが生成されていなければ,生成&初期化
      if(folderBrowser==null)
      {
        folderBrowser=new FolderBrowserDialog();
        InitializeDialog(folderBrowser);
      }

      // valueが文字列ならパスに設定
      if(value is string)
      {
        folderBrowser.SelectedPath=value.ToString();
      }
      if(folderBrowser.ShowDialog()!=DialogResult.OK)
      {
        return value;
      }

      return folderBrowser.SelectedPath;
    }

    public override UITypeEditorEditStyle GetEditStyle(
      ITypeDescriptorContext context)
    {
      return UITypeEditorEditStyle.Modal;
    }

    protected virtual void InitializeDialog(FolderBrowserDialog browserDialog)
    {
      // Todo: 
      browserDialog.Description="対象とするフォルダへのパスを選択してください。";
    }
  }
}

なお、このコード中には「Todo:」というコメントが入っています。 ファイル選択ダイアログの説明文を設定しているのですが、見てのとおり日本語の文字列をハード・コーディングしています。 これはあまり褒められたことではないので、実際に用いるときは適宜 変更してみてください。 あらかじめResourceManager クラスの静的インスタンスを用意しておけば、この部分もローカライズすることができます。


戻る