.NET Framework PropertyGrid コントロールを最大限に活用する

 

ライドアウトをマークする
Microsoft Corporation

適用対象:
   Microsoft® .NET® Framework
   Microsoft® Visual Studio® .NET

概要:Microsoft .NET Frameworkの PropertyGrid コントロールと、アプリケーション用にカスタマイズする方法を理解するのに役立ちます。 (37ページ印刷)

内容

PropertyGrid コントロールの概要
PropertyGrid コントロールの作成
PropertyGrid コントロールを使用する場所
オブジェクトの選択
PropertyGrid コントロールのカスタマイズ
複合プロパティの表示
プロパティにカスタム UI を提供する
まとめ

PropertyGrid コントロールの概要

Microsoft Visual Basic® または Microsoft® Visual Studio .NET を使用している場合は、プロパティ ブラウザーを使用して、1 つ以上のオブジェクトのプロパティを参照、表示、および編集しました。 .NET Framework PropertyGrid コントロールは、Visual Studio .NET 内のプロパティ ブラウザーの中核です。 PropertyGrid コントロールは、オブジェクトまたは型のプロパティを表示し、主にリフレクションを使用してアイテムのプロパティを取得します。 (リフレクションは、実行時に型情報を提供するテクノロジです)。

次のスクリーン ショットは、フォームに配置されたときの PropertyGrid の外観を示しています。

図 1. フォームの PropertyGrid

PropertyGrid には、次の部分が含まれています。

  • プロパティ
  • 展開可能なプロパティ
  • プロパティ カテゴリの見出し
  • プロパティの説明
  • プロパティ エディター
  • プロパティ タブ
  • コマンド ウィンドウ (コントロールのデザイナーが公開するデザイナー動詞が表示されます)

PropertyGrid コントロールの作成

Visual Studio .NET を使用して PropertyGrid コントロールを作成するには、既定では含まれていない ため、PropertyGrid コントロールをツールボックスに追加する必要があります。 [ツール] メニューの [ツールボックスのカスタマイズ] を選択します。 ダイアログ ボックスで、[ フレームワーク コンポーネント ] タブを選択し、[ PropertyGrid] を選択します。

コマンド ラインからコードをコンパイルする場合は、 /reference オプションを使用し、System.Windows.Forms.dllを指定します。

次のコードは、 PropertyGrid コントロールを作成し、フォームに追加する方法を示しています。

' Visual Basic

Imports System
Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Globalization

Public Class OptionsDialog
   Inherits System.Windows.Forms.Form

   Private OptionsPropertyGrid As System.Windows.Forms.PropertyGrid

   Public Sub New()
      MyBase.New()

      OptionsPropertyGrid = New PropertyGrid()
      OptionsPropertyGrid.Size = New Size(300, 250)

      Me.Controls.Add(OptionsPropertyGrid)
      Me.Text = "Options Dialog"
   End Sub
End Class


//C#

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

public class OptionsDialog : System.Windows.Forms.Form
{
   private System.Windows.Forms.PropertyGrid OptionsPropertyGrid;
   public OptionsDialog()
   {
      OptionsPropertyGrid = new PropertyGrid();
      OptionsPropertyGrid.Size = new Size(300, 250);

      this.Controls.Add(OptionsPropertyGrid);
      this.Text = "Options Dialog";
   }

   [STAThread]
   static void Main() 
   {
      Application.Run(new OptionsDialog());
   }
}

PropertyGrid コントロールを使用する場所

アプリケーションには、 PropertyGrid をユーザーに操作させることで、より豊富な編集エクスペリエンスを提供する必要がある場所が多数あります。 1 つの例として、ユーザーが設定できる "設定" またはオプションが複数あり、その一部が複雑なアプリケーションです。 これらのオプションを表すには、ラジオ ボタン、コンボ ボックス、またはテキスト ボックスを使用できます。 代わりに、 PropertyGrid コントロールを使用してアプリケーション オプションを設定するためのオプション ウィンドウを作成するプロセスについて説明します。 OptionsDialog上記で作成したフォームは、オプション ウィンドウの先頭になります。 次に、アプリケーション設定にマップされるすべてのプロパティを含む という名前 AppSettings のクラスを作成します。 個々の変数を使用するのではなく、個別のクラスを作成すると、設定の管理と保守がはるかに簡単になります。

' Visual Basic

Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "Welcome to your application!"
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4

    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"

    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property

    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property

    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property

    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property

    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property

    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class


//C#

public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "Welcome to your application!";
    private int itemsInMRU = 4;
    private int maxRepeatRate = 10;
    private bool settingsChanged = false;
    private string appVersion = "1.0";
    
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

オプション ウィンドウの PropertyGrid はこのクラスを操作するため、新しいファイルまたはフォームのソース コードの下部にあるアプリケーション プロジェクトにクラス定義を追加します。

オブジェクトの選択

PropertyGrid に表示される内容を識別するには、PropertyGrid.SelectedObject プロパティをオブジェクト インスタンスに設定します。 PropertyGrid は残りの処理を行います。 SelectedObject を設定するたびに、PropertyGrid によって表示されるプロパティが更新されます。 これにより、プロパティを強制的に更新したり、実行時にオブジェクトを切り替えたりする簡単な方法が提供されます。 PropertyGrid.Refresh メソッドを呼び出してプロパティを更新することもできます。

続行するには、コンストラクター内のコードを OptionsDialog 更新してオブジェクトを AppSettings 作成し、 PropertyGrid.SelectedObject プロパティに設定します。

' Visual Basic

   Public Sub New()
      MyBase.New()

      OptionsPropertyGrid = New PropertyGrid()
      OptionsPropertyGrid.Size = New Size(300, 250)

      Me.Controls.Add(OptionsPropertyGrid)
      Me.Text = "Options Dialog"

      ' Create the AppSettings class and display it in the PropertyGrid.      Dim appset as AppSettings = New AppSettings()      OptionsPropertyGrid.SelectedObject = appset
   End Sub


//C#

   public OptionsDialog()
   {
      OptionsPropertyGrid = new PropertyGrid();
      OptionsPropertyGrid.Size = new Size(300, 250);

      this.Controls.Add(OptionsPropertyGrid);
      this.Text = "Options Dialog";

      // Create the AppSettings class and display it in the PropertyGrid.      AppSettings appset = new AppSettings();      OptionsPropertyGrid.SelectedObject = appset;
   }

アプリケーションをコンパイルして実行します。 次のスクリーン ショットは、その外観を示しています。

図 2. PropertyGrid で選択された AppSettings クラス

PropertyGrid コントロールのカスタマイズ

PropertyGrid の視覚的な側面をニーズに合わせて変更できます。 一部のプロパティの表示方法を変更し、一部のプロパティを表示しないことを選択することもできます。 PropertyGrid のカスタマイズ方法

PropertyGrid の視覚的側面の変更

PropertyGrid の多くの視覚的側面はカスタマイズ可能です。 その一部を以下に紹介します。

  • HelpBackColor、HelpForeColorHelpVisible プロパティを使用して、背景色の変更、フォントの色の変更、説明ウィンドウの非表示を切り替えます。
  • ToolbarVisible プロパティを使用してツール バーを非表示にし、BackColor プロパティで色を変更し、LargeButtons プロパティを使用して大きなツール バー ボタンを表示します。
  • プロパティをアルファベット順に並べ替え、 PropertySort プロパティを使用して分類します。
  • BackColor プロパティを使用してスプリッターの色を変更します。
  • LineColor プロパティを使用して、グリッド線と罫線を変更します。

この例のオプション ウィンドウでは、ツール バーは必要ないので、 ToolbarVisible を false に設定 します。 その他の既定の設定はそのままにします。

プロパティの表示方法の変更

一部のプロパティの表示方法を変更するには、プロパティに異なる属性を適用できます。 属性は、リフレクションを使用して実行時に取得できる型、フィールド、メソッド、プロパティなどのプログラミング要素に注釈を付けるために使用される宣言型タグです。 その一部を以下に紹介します。

  • DescriptionAttribute。 プロパティの下にある説明ヘルプ ウィンドウに表示されるプロパティのテキストを設定します。 これは、作業中のプロパティ (フォーカスがあるプロパティ) のヘルプ テキストを提供する便利な方法です。 この属性を プロパティに MaxRepeatRate 適用します。
  • CategoryAttribute。 グリッド内のプロパティの下にあるカテゴリを設定します。 これは、プロパティをカテゴリ名でグループ化する場合に便利です。 プロパティにカテゴリが指定されていない場合は、 その他 のカテゴリに割り当てられます。 この属性をすべてのプロパティに適用します。
  • BrowsableAttribute – プロパティがグリッドに表示されるかどうかを示します。 これは、グリッドからプロパティを非表示にする場合に便利です。 既定では、パブリック プロパティは常にグリッドに表示されます。 この属性を プロパティに SettingsChanged 適用します。
  • ReadOnlyAttribute – プロパティが読み取り専用かどうかを示します。 これは、グリッド内でプロパティを編集できないようにする場合に便利です。 既定では、get および set アクセサー関数を持つパブリック プロパティは、グリッドで編集可能です。 この属性を プロパティに AppVersion 適用します。
  • DefaultValueAttribute – プロパティの既定値を識別します。 これは、プロパティの既定値を指定し、後でプロパティの値が既定値と異なるかどうかを判断する場合に便利です。 この属性をすべてのプロパティに適用します。
  • DefaultPropertyAttribute – クラスの既定のプロパティを識別します。 クラスの既定のプロパティは、グリッドでクラスが選択されたときに最初にフォーカスを取得します。 この属性を クラスに AppSettings 適用します。

次に、これらの属性の一部を AppSettings クラスに適用して、PropertyGrid でのプロパティの表示方法を変更 します。

' Visual Basic

<DefaultPropertyAttribute("SaveOnClose")> _
Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "Welcome to your application!"
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4

    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"

    <CategoryAttribute("Document Settings"), _     DefaultValueAttribute(True)> _
    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property

    <CategoryAttribute("Global Settings"), _    ReadOnlyAttribute(True), _    DefaultValueAttribute("Welcome to your application!")> _
    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property

    <CategoryAttribute("Global Settings"), _    DefaultValueAttribute(4)> _
    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property

    <DescriptionAttribute("The rate in milliseconds that the text will repeat."), _    CategoryAttribute("Global Settings"), _    DefaultValueAttribute(10)> _
    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property

    <BrowsableAttribute(False),     DefaultValueAttribute(False)> _
    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property

    <CategoryAttribute("Version"), _    DefaultValueAttribute("1.0"), _    ReadOnlyAttribute(True)> _
    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class


//C#[DefaultPropertyAttribute("SaveOnClose")]
public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "Welcome to your application!";
    private int maxRepeatRate = 10;
    private int itemsInMRU = 4;

    private bool settingsChanged = false;
    private string appVersion = "1.0";

    [CategoryAttribute("Document Settings"),    DefaultValueAttribute(true)]
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }

    [CategoryAttribute("Global Settings"),    ReadOnlyAttribute(true),    DefaultValueAttribute("Welcome to your application!")]
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }

    [CategoryAttribute("Global Settings"),    DefaultValueAttribute(4)]
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }

    [DescriptionAttribute("The rate in milliseconds that the text will repeat."),    CategoryAttribute("Global Settings"),    DefaultValueAttribute(10)]
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }

    [BrowsableAttribute(false),    DefaultValueAttribute(false)]
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }

    [CategoryAttribute("Version"),    DefaultValueAttribute("1.0"),    ReadOnlyAttribute(true)]
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

これらの属性を クラスに適用してAppSettings 、アプリケーションをコンパイルして実行します。 次のスクリーン ショットは、その外観を示しています。

図 3: PropertyGrid にカテゴリと既定値と共に表示されるプロパティ

このバージョンのオプション ウィンドウを操作した後、次のことに気付く場合があります。

  • プロパティは SaveOnClose 、ウィンドウが表示されるときにフォーカスを取得します。
  • プロパティを MaxRepeatRate 選択すると、説明ヘルプ ウィンドウに "テキストが繰り返される速度 (ミリ秒単位) が表示されます。
  • プロパティは SaveOnClose 、"ドキュメント設定" カテゴリの下に表示されます。 その他のプロパティは、"グローバル設定" と "バージョン" という名前の他の 2 つのカテゴリの下に表示されます。
  • SettingsChangedプロパティは表示されなくなりました。
  • AppVersion プロパティは読み取り専用です。 読み取り専用プロパティは、淡色表示されたテキストで表示されます。
  • プロパティに true 以外のSaveOnClose値がある場合は、太字で表示されます。 PropertyGrid では、太字のテキストを使用して、既定値以外の値を持つプロパティを示します。

複合プロパティの表示

これまで、オプション ウィンドウには、整数、ブール値、文字列などの単純な型が表示されています。 より複雑な型はどうですか? アプリケーションでウィンドウ サイズ、ドキュメント フォント、ツール バーの色などを追跡する必要がある場合はどうしますか? .NET Frameworkによって提供される一部のデータ型には、PropertyGrid でより使いやすくするために役立つ特別な表示機能があります。

指定された型のサポート

まず、 クラスを AppSettings 更新して、ウィンドウ サイズ (サイズ の種類)、ウィンドウ フォント (フォント の種類)、およびツール バーの色 ( の種類) の新しいプロパティを追加します。

' Visual Basic

<DefaultPropertyAttribute("SaveOnClose")> _
Public Class AppSettings
    Private _saveOnClose As Boolean = True
    Private _greetingText As String = "Welcome to your application!"
    Private _maxRepeatRate As Integer = 10
    Private _itemsInMRU As Integer = 4

    Private _settingsChanged As Boolean = False
    Private _appVersion As String = "1.0"

    Private _windowSize As Size = New Size(100, 100)    Private _windowFont As Font = New Font("Arial", 8, FontStyle.Regular)    Private _toolbarColor As Color = SystemColors.Control

    <CategoryAttribute("Document Settings"), _
     DefaultValueAttribute(True)> _
    Public Property SaveOnClose() As Boolean
        Get
            Return _saveOnClose
        End Get
        Set(ByVal Value As Boolean)
            SaveOnClose = Value
        End Set
    End Property

    <CategoryAttribute("Document Settings")> _    Public Property WindowSize() As Size        Get            Return _windowSize        End Get        Set(ByVal Value As Size)            _windowSize = Value        End Set    End Property    <CategoryAttribute("Document Settings")> _    Public Property WindowFont() As Font        Get            Return _windowFont        End Get        Set(ByVal Value As Font)            _windowFont = Value        End Set    End Property    <CategoryAttribute("Global Settings")> _    Public Property ToolbarColor() As Color        Get            Return _toolbarColor        End Get        Set(ByVal Value As Color)            _toolbarColor = Value        End Set    End Property

    <CategoryAttribute("Global Settings"), _
    ReadOnlyAttribute(True), _
    DefaultValueAttribute("Welcome to your application!")> _
    Public Property GreetingText() As String
        Get
            Return _greetingText
        End Get
        Set(ByVal Value As String)
            _greetingText = Value
        End Set
    End Property

    <CategoryAttribute("Global Settings"), _
    DefaultValueAttribute(4)> _
    Public Property ItemsInMRUList() As Integer
        Get
            Return _itemsInMRU
        End Get
        Set(ByVal Value As Integer)
            _itemsInMRU = Value
        End Set
    End Property

    <DescriptionAttribute("The rate in milliseconds that the text will repeat."), _
    CategoryAttribute("Global Settings"), _
    DefaultValueAttribute(10)> _
    Public Property MaxRepeatRate() As Integer
        Get
            Return _maxRepeatRate
        End Get
        Set(ByVal Value As Integer)
            _maxRepeatRate = Value
        End Set
    End Property

    <BrowsableAttribute(False),
     DefaultValueAttribute(False)> _
    Public Property SettingsChanged() As Boolean
        Get
            Return _settingsChanged
        End Get
        Set(ByVal Value As Boolean)
            _settingsChanged = Value
        End Set
    End Property

    <CategoryAttribute("Version"), _
    DefaultValueAttribute("1.0"), _
    ReadOnlyAttribute(True)> _
    Public Property AppVersion() As String
        Get
            Return _appVersion
        End Get
        Set(ByVal Value As String)
            _appVersion = Value
        End Set
    End Property
End Class


//C#

[DefaultPropertyAttribute("SaveOnClose")]
public class AppSettings{
    private bool saveOnClose = true;
    private string greetingText = "Welcome to your application!";
    private int maxRepeatRate = 10;
    private int itemsInMRU = 4;

    private bool settingsChanged = false;
    private string appVersion = "1.0";
    
    private Size windowSize = new Size(100,100);    private Font windowFont = new Font("Arial", 8, FontStyle.Regular);    private Color toolbarColor = SystemColors.Control;

    [CategoryAttribute("Document Settings"),
    DefaultValueAttribute(true)]
    public bool SaveOnClose
    {
        get { return saveOnClose; }
        set { saveOnClose = value;}
    }

    [CategoryAttribute("Document Settings")]    public Size WindowSize     {        get { return windowSize; }        set { windowSize = value;}    }    [CategoryAttribute("Document Settings")]    public Font WindowFont     {        get {return windowFont; }        set { windowFont = value;}    }    [CategoryAttribute("Global Settings")]    public Color ToolbarColor    {        get { return toolbarColor; }        set { toolbarColor = value; }    }

    [CategoryAttribute("Global Settings"),
    ReadOnlyAttribute(true),
    DefaultValueAttribute("Welcome to your application!")]
    public string GreetingText
    {
        get { return greetingText; }
        set { greetingText = value; }
    }

    [CategoryAttribute("Global Settings"),
    DefaultValueAttribute(4)]
    public int ItemsInMRUList
    {
        get { return itemsInMRU; }
        set { itemsInMRU = value; }
    }

    [DescriptionAttribute("The rate in milliseconds that the text will repeat."),
    CategoryAttribute("Global Settings"),
    DefaultValueAttribute(10)]
    public int MaxRepeatRate
    {
        get { return maxRepeatRate; }
        set { maxRepeatRate = value; }
    }

    [BrowsableAttribute(false),
    DefaultValueAttribute(false)]
    public bool SettingsChanged
    {
        get { return settingsChanged; }
        set { settingsChanged = value; }
    }

    [CategoryAttribute("Version"),
    DefaultValueAttribute("1.0"),
    ReadOnlyAttribute(true)]
    public string AppVersion
    {
        get { return appVersion; }
        set { appVersion = value; }
    }
}

次のスクリーン ショットは、 PropertyGrid での新しいプロパティの外観を示しています。

図 4: PropertyGrid に表示される.NET Frameworkデータ型

プロパティには WindowFont 省略記号 ("...") ボタンがあり、押すとフォント選択ダイアログが表示されます。 さらに、 プロパティを展開して、より多くの Font プロパティを表示することもできます。 Font プロパティの一部には、フォントに関する値と詳細のドロップダウン リストが用意されています。 プロパティを WindowSize 展開して、 Size 型のその他のプロパティを表示できます。 最後に、プロパティに ToolbarColor 選択した色の見本と、さまざまな色を選択するためのカスタム ドロップダウン リストがあることに注意してください。 これらのデータ型などの場合、.NET Frameworkには PropertyGrid での編集を容易にする追加のクラスが用意されています。

カスタム型のサポート

次に、 クラスにさらに 2 つのプロパティを AppSettings 追加します。1 つは と呼ばれ DefaultFileName 、もう 1 つは と呼ばれます SpellCheckOptions。 プロパティは DefaultFileName 文字列を取得または設定し、プロパティは SpellCheckOptions クラスの SpellingOptions インスタンスを取得または設定します。

クラスは SpellingOptions 、アプリケーションのスペル チェック プロパティを管理する新しいクラスです。 オブジェクトのプロパティを管理するために別のクラスを作成するタイミングに関するハードで高速なルールはありません。これは、クラス全体の設計によって異なります。 新しいファイルまたはフォームの SpellingOptions ソース コードの下部に、クラス定義をアプリケーション プロジェクトに追加します。

' Visual Basic

<DescriptionAttribute("Expand to see the spelling options for the application.")> _
Public Class SpellingOptions
    Private _spellCheckWhileTyping As Boolean = True
    Private _spellCheckCAPS As Boolean = False
    Private _suggestCorrections As Boolean = True

    <DefaultValueAttribute(True)> _
    Public Property SpellCheckWhileTyping() As Boolean
        Get
            Return _spellCheckWhileTyping
        End Get
        Set(ByVal Value As Boolean)
            _spellCheckWhileTyping = Value
        End Set
    End Property

    <DefaultValueAttribute(False)> _
    Public Property SpellCheckCAPS() As Boolean
        Get
            Return _spellCheckCAPS
        End Get
        Set(ByVal Value As Boolean)
            _spellCheckCAPS = Value
        End Set
    End Property

    <DefaultValueAttribute(True)> _
    Public Property SuggestCorrections() As Boolean
        Get
            Return _suggestCorrections
        End Get
        Set(ByVal Value As Boolean)
            _suggestCorrections = Value
        End Set
    End Property
End Class


//C#

[DescriptionAttribute("Expand to see the spelling options for the application.")]
public class SpellingOptions{
    private bool spellCheckWhileTyping = true;
    private bool spellCheckCAPS = false;
    private bool suggestCorrections = true;

    [DefaultValueAttribute(true)]
    public bool SpellCheckWhileTyping 
    {
        get { return spellCheckWhileTyping; }
        set { spellCheckWhileTyping = value; }
    }

    [DefaultValueAttribute(false)]
    public bool SpellCheckCAPS 
    {
        get { return spellCheckCAPS; }
        set { spellCheckCAPS = value; }
    }
    [DefaultValueAttribute(true)]
    public bool SuggestCorrections 
    {
        get { return suggestCorrections; }
        set { suggestCorrections = value; }
    }
}

オプション ウィンドウ アプリケーションをもう一度コンパイルして実行します。 次のスクリーン ショットは、その外観を示しています。

図 5: PropertyGrid に表示される、型コンバーターのないカスタム データ型

プロパティの外観に SpellcheckOptions 注目してください。 .NET Framework型とは異なり、カスタム文字列表現は展開または表示されません。 .NET Framework型が独自の複合型に持つのと同じ編集エクスペリエンスを提供する場合はどうなりますか? .NET Framework型では、TypeConverter クラスと UITypeEditor クラスを使用して、PropertyGrid 編集のサポートの大部分を提供します。また、それらを使用することもできます。

展開可能なプロパティのサポートの追加

PropertyGrid を取得してプロパティをSpellingOptions展開するには、TypeConverter を作成する必要があります。 TypeConverter は、ある型から別の型に変換する方法を提供します。 PropertyGridTypeConverter を使用してオブジェクトの種類を String に変換し、これを使用してグリッドにオブジェクト値を表示します。 編集中に、 TypeConverterString からオブジェクト型に変換します。 .NET Frameworkは、これを簡単にするために ExpandableObjectConverter クラスを提供します。

拡張可能なオブジェクトのサポートを提供するには

  1. ExpandableObjectConverter から継承するクラスを作成します。

    ' Visual Basic
    
    Public Class SpellingOptionsConverter
        Inherits ExpandableObjectConverter
    End Class
    
    
    //C#
    
    public class SpellingOptionsConverter:ExpandableObjectConverter 
    {  }
    
  2. CanConvertTo メソッドをオーバーライドし、パラメーターがこの型コンバーター (SpellingOptions例のクラス) を使用するクラスと同じ型である場合destinationTypetrue を返します。それ以外の場合は、基底クラスの CanConvertTo メソッドの値を返します。

    ' Visual Basic
    
    Public Overloads Overrides Function CanConvertTo( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal destinationType As Type) As Boolean
        If (destinationType Is GetType(SpellingOptions)) Then
            Return True
        End If
        Return MyBase.CanConvertFrom(context, destinationType)
    End Function
    
    //C#
    
    public override bool CanConvertTo(ITypeDescriptorContext context,
                                      System.Type destinationType) 
    {
        if (destinationType == typeof(SpellingOptions))
            return true;
    
        return base.CanConvertTo(context, destinationType);
    }
    
  3. ConvertTo メソッドをオーバーライドし、パラメーターが String であり、値がこの型コンバーター (SpellingOptions例のクラス) を使用するクラスと同じ型であることを確認destinationTypeします。 どちらの場合も false の場合は、基底クラス ConvertTo メソッドの値を返します。それ以外の場合は、値オブジェクトの文字列表現を返します。 文字列表現では、クラスの各プロパティを一意の区切り記号で区切る必要があります。 文字列全体が PropertyGrid に表示されるため、読みやすさを損なわない区切り記号を選択します。通常、コンマは適切に機能します。

    ' Visual Basic
    
    Public Overloads Overrides Function ConvertTo( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal culture As CultureInfo, _
                                  ByVal value As Object, _
                                  ByVal destinationType As System.Type) _
                         As Object
        If (destinationType Is GetType(System.String) _
            AndAlso TypeOf value Is SpellingOptions) Then
    
            Dim so As SpellingOptions = CType(value, SpellingOptions)
    
            Return "Check while typing: " & so.SpellCheckWhileTyping & _
                   ", check CAPS: " & so.SpellCheckCAPS & _
                   ", suggest corrections: " & so.SuggestCorrections
        End If
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function
    
    //C#
    
    public override object ConvertTo(ITypeDescriptorContext context,
                                   CultureInfo culture, 
                                   object value, 
                                   System.Type destinationType) 
    {
        if (destinationType == typeof(System.String) && 
             value is SpellingOptions){
    
            SpellingOptions so = (SpellingOptions)value;
    
            return "Check while typing:" + so.SpellCheckWhileTyping + 
                   ", check CAPS: " + so.SpellCheckCAPS +
                   ", suggest corrections: " + so.SuggestCorrections;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
    
  4. (省略可能)型コンバーターが文字列から変換できることを指定することで、グリッド内のオブジェクトの文字列表現の編集を有効にすることができます。 これを行うには、最初に CanConvertFrom メソッドをオーバーライドし、source Type パラメーターが String 型の場合は true を返します。それ以外の場合は、基底クラスの CanConvertFrom メソッドの値を返します。

    ' Visual Basic
    
    Public Overloads Overrides Function CanConvertFrom( _
                               ByVal context As ITypeDescriptorContext, _
                               ByVal sourceType As System.Type) As Boolean
        If (sourceType Is GetType(String)) Then
            Return True
        End If
        Return MyBase.CanConvertFrom(context, sourceType)
    End Function
    
    //C#
    
    public override bool CanConvertFrom(ITypeDescriptorContext context,
                                  System.Type sourceType) 
    {
        if (sourceType == typeof(string))
            return true;
    
        return base.CanConvertFrom(context, sourceType);
    }
    
  5. オブジェクトの基底クラスの編集を有効にするには、 ConvertFrom メソッドをオーバーライドし、value パラメーターが String であることを確認する必要もあります。 文字列でない場合は、基底クラス ConvertFrom メソッドの値を返します。それ以外の場合は、value パラメーターに基づいてクラス (SpellingOptions例のクラス) の新しいインスタンスを返します。 value パラメーターからクラスの各プロパティの値を解析する必要があります。 ConvertTo メソッドで作成した区切り文字列の形式を把握することは、解析の実行に役立ちます。

    ' Visual Basic
    
    Public Overloads Overrides Function ConvertFrom( _
                                  ByVal context As ITypeDescriptorContext, _
                                  ByVal culture As CultureInfo, _
                                  ByVal value As Object) As Object
    
        If (TypeOf value Is String) Then
            Try
                Dim s As String = CStr(value)
                Dim colon As Integer = s.IndexOf(":")
                Dim comma As Integer = s.IndexOf(",")
    
                If (colon <> -1 AndAlso comma <> -1) Then
                    Dim checkWhileTyping As String = s.Substring(colon + 1, _
                                                    (comma - colon - 1))
    
                    colon = s.IndexOf(":", comma + 1)
                    comma = s.IndexOf(",", comma + 1)
    
                    Dim checkCaps As String = s.Substring(colon + 1, _
                                                    (comma - colon - 1))
    
                    colon = s.IndexOf(":", comma + 1)
    
                    Dim suggCorr As String = s.Substring(colon + 1)
    
                    Dim so As SpellingOptions = New SpellingOptions()
    
                    so.SpellCheckWhileTyping = Boolean.Parse(checkWhileTyping)
                    so.SpellCheckCAPS = Boolean.Parse(checkCaps)
                    so.SuggestCorrections = Boolean.Parse(suggCorr)
    
                    Return so
                End If
            Catch
                Throw New ArgumentException( _
                    "Can not convert '" & CStr(value) & _ 
                                      "' to type SpellingOptions")
    
            End Try
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function
    
    //C#
    
    public override object ConvertFrom(ITypeDescriptorContext context,
                                  CultureInfo culture, object value) 
    {
        if (value is string) {
            try {
                string s = (string) value;
                int colon = s.IndexOf(':');
                int comma = s.IndexOf(',');
    
                if (colon != -1 && comma != -1) {
                    string checkWhileTyping = s.Substring(colon + 1 ,
                                                    (comma - colon - 1));
    
                    colon = s.IndexOf(':', comma + 1);
                    comma = s.IndexOf(',', comma + 1);
    
                    string checkCaps = s.Substring(colon + 1 , 
                                                    (comma - colon -1));
    
                    colon = s.IndexOf(':', comma + 1);
    
                    string suggCorr = s.Substring(colon + 1);
    
                    SpellingOptions so = new SpellingOptions();
    
                    so.SpellCheckWhileTyping =Boolean.Parse(checkWhileTyping);
                    so.SpellCheckCAPS = Boolean.Parse(checkCaps);
                    so.SuggestCorrections = Boolean.Parse(suggCorr);
    
                    return so;
                }
            }
            catch {
                throw new ArgumentException(
                    "Can not convert '" + (string)value + 
                                       "' to type SpellingOptions");
            }
        }  
        return base.ConvertFrom(context, culture, value);
    }
    
  6. 型コンバーター クラスが作成されたので、それを使用するターゲット クラスを識別する必要があります。 これを行うには、 TypeConverterAttribute をターゲット クラス ( SpellingOptions 例のクラス) に適用します。

    ' Visual Basic
    
    ' The TypeConverter attribute applied to the SpellingOptions class.
    <TypeConverter(GetType(SpellingOptionsConverter)), _
    DescriptionAttribute("Expand to see the spelling options for the application.")> _
    Public Class SpellingOptions
       ...
    End Class
    
    
    //C#
    
    // The TypeConverter attribute applied to the SpellingOptions class.
     [TypeConverterAttribute(typeof(SpellingOptionsConverter)),
    DescriptionAttribute("Expand to see the spelling options for the application.")]
    public class SpellingOptions{ ... }
    

オプション ウィンドウ アプリケーションをもう一度コンパイルして実行します。 次のスクリーン ショットは、オプション ウィンドウがどのように表示されるかを示しています。

図 6: PropertyGrid に表示される型コンバーターを使用したカスタム データ型

** ** 拡張可能なオブジェクトのサポートのみを必要とするが、カスタム文字列表現は必要ない場合は、 単に TypeConverterAttribute をクラスに適用できます。 型コンバーターの型として ExpandableObjectConverter を指定します。

ドメイン リストと単純なドロップダウン プロパティのサポートの追加

Enum 型に基づいて列挙を返すプロパティの場合、PropertyGrid は列挙値をドロップダウン リストに自動的に表示します。 EnumConverter には、この機能も用意されています。 プロパティを所有している場合は、 Enum に基づいていない型を使用して、ユーザーに有効な値のリスト (選択リストまたはドメイン リストと呼ばれることもあります) を提供できます。 これは、実行時までドメイン値が不明な場合、または値が変更される可能性がある場合です。

オプション ウィンドウを変更して、ユーザーが選択できる既定のファイル名のドメイン 一覧を提供します。 プロパティは既に DefaultFileName クラスに AppSettings 追加されています。 次の手順では、ドメイン リストを指定するために、 PropertyGrid の プロパティのドロップダウンを表示します。

簡単なドロップダウン プロパティのサポートを提供するには

  1. 型コンバーター クラスから継承するクラスを作成します。 DefaultFileNameプロパティは String 型であるため、StringConverter から継承できます。 プロパティの型の型コンバーターが存在しない場合は、 TypeConverter から継承できます。この場合は必要ありません。

    ' Visual Basic
    
    Public Class FileNameConverter
        Inherits StringConverter
    End Class
    
    
    //C#
    
    public class FileNameConverter: StringConverter 
    {  } 
    
  2. GetStandardValuesSupported メソッドをオーバーライドし、true を返して、このオブジェクトがリストから選択できる標準の値セットをサポートしていることを示します。

    ' Visual Basic
    
    Public Overloads Overrides Function GetStandardValuesSupported( _
                        ByVal context As ITypeDescriptorContext) As Boolean
        Return True
    End Function
    
    
    //C#
    
    public override bool GetStandardValuesSupported(
                               ITypeDescriptorContext context) 
    {
        return true;
    }
    
  3. GetStandardValues メソッドをオーバーライドし、標準値が入力された StandardValuesCollection を返します。 StandardValuesCollection を作成する 1 つの方法は、コンストラクターに値の配列を指定することです。 オプション ウィンドウ アプリケーションでは、提案された既定のファイル名で埋められた 文字列 配列を使用できます。

    ' Visual Basic
    
    Public Overloads Overrides Function GetStandardValues( _
                         ByVal context As ITypeDescriptorContext) _
                      As StandardValuesCollection
    
        Return New StandardValuesCollection(New String() {"New File", _
                                                          "File1", _
                                                          "Document1"})
    End Function 
    
    
    //C#
    
    public override StandardValuesCollection
                         GetStandardValues(ITypeDescriptorContext context) 
    {
        return new StandardValuesCollection(new string[]{"New File", 
                                                         "File1", 
                                                         "Document1"});
    } 
    
  4. (省略可能)ドロップダウン リストにない値をユーザーが入力できるようにするには、 GetStandardValuesExclusive メソッドをオーバーライドし、 false を返します。 これにより、基本的にドロップダウン リストのスタイルがコンボ ボックス スタイルに変更されます。

    ' Visual Basic
    
    Public Overloads Overrides Function GetStandardValuesExclusive( _
                   ByVal context As ITypeDescriptorContext) As Boolean
        Return False
    End Function
    
    
    //C#
    
    public override bool GetStandardValuesExclusive(
                               ITypeDescriptorContext context) 
    {
        return false;
    }
    
  5. ドロップダウン リストを表示するための独自の型コンバーター クラスが用意されたので、それを使用するターゲットを特定する必要があります。 この場合、型コンバーターは プロパティに DefaultFileName 固有であるため、ターゲットは プロパティです。 TypeConverterAttribute をターゲット プロパティに適用します。

    ' Visual Basic
    
    ' The TypeConverter attribute applied to the DefaultFileName property.
    <TypeConverter(GetType(FileNameConverter)),_
     CategoryAttribute("Document Settings")> _
    Public Property DefaultFileName() As String
        Get
            Return _defaultFileName
        End Get
        Set(ByVal Value As String)
            _defaultFileName = Value
        End Set
    End Property
    
    
    //C#
    
    // The TypeConverter attribute applied to the DefaultFileName property.
     [TypeConverter(typeof(FileNameConverter)),
     CategoryAttribute("Document Settings")]
    public string DefaultFileName
    {
        get{ return defaultFileName; }
        set{ defaultFileName = value; }
    }
    

オプション ウィンドウ アプリケーションをもう一度コンパイルして実行します。 次のスクリーン ショットは、オプション ウィンドウがどのように表示されるかを示しています。 プロパティの表示方法に DefaultFileName 注目してください。

図 7: PropertyGrid にドロップダウン ドメイン リストを表示する

プロパティにカスタム UI を提供する

前述のように、.NET Framework型では、TypeConverter クラスと UITypeEditor クラス (他のクラスと共に) を使用して、PropertyGrid 編集のサポートを提供します。 「カスタム型のサポート」セクションでは、 TypeConverter の使用について説明しました。 UITypeEditor クラスを使用して、独自の PropertyGrid カスタマイズを実行することもできます。

Image クラスと Color クラスに用意されているのと同様に、PropertyGrid のプロパティ値と共に小さなグラフィカル表現を提供できます。 カスタマイズのためにこれを行うには、 UITypeEditor から継承し、 GetPaintValueSupported を オーバーライドして true を返します。 次 に、UITypeEditor.PaintValue メソッドをオーバーライドし、メソッドで PaintValueEventArgs.Graphics パラメーターを使用してグラフィックを描画します。 最後に、UITypeEditor クラスを使用するクラスまたはプロパティに Editor 属性を適用します。

次のスクリーン ショットは、結果の外観を示しています。

図 8: PropertyGrid でプロパティのカスタム グラフィックを表示する

Control.Dock プロパティを使用してユーザーのドッキングを選択する場合と同様に、独自のドロップダウン リスト コントロールを指定することもできます。 これを行うには、 UITypeEditor から継承し、 GetEditStyle をオーバーライドして、 DROPDown などの UITypeEditorEditStyle 列挙値を返 します。 カスタム ドロップダウン コントロールは、 Control または Control 派生クラス ( UserControl など) から継承する必要があります。 次に、 UITypeEditor.EditValue メソッドを オーバーライドします。 IServiceProvider パラメーターを使用して、IServiceProvider.GetService メソッドを呼び出して IWindowsFormsEditorService インスタンスを取得します。 最後に、 IWindowsFormsEditorService.DropDownControl メソッドを呼び出して、カスタム ドロップダウン リスト コントロールを表示します。 UITypeEditor クラスを使用するクラスまたはプロパティには、必ず Editor 属性を適用してください。

次のスクリーン ショットは、結果の外観を示しています。

図 9: PropertyGrid でプロパティのカスタム ドロップダウン コントロールを表示する

TypeEditor クラスと UITypeEditor クラスを使用するだけでなく、PropertyGrid をカスタマイズして追加のプロパティ タブを表示することもできます。 プロパティ タブは PropertyTab クラスから継承されます。 Microsoft Visual C# ™ .NET でプロパティ ブラウザーを使用している場合は、カスタム PropertyTab が表示されている可能性があります。[ イベント ] タブ (稲妻付きのボタン) はカスタム PropertyTab です。 次のスクリーン ショットは、カスタム PropertyTab の別の例を示しています。 この PropertyTab は 、ボタンの境界ポイントを編集してカスタム ボタン図形を作成する機能を提供します。

図 10: PropertyGrid でのカスタム タブの表示

UITypeEditor クラスを使用して PropertyGrid をカスタマイズする方法の詳細と、上記のカスタム ユーザー インターフェイスのコード例、Shawn Burke の記事「Make Your Components Really RAD with Visual Studio .NET Property Browser」を参照してください。

まとめ

.NET Frameworkによって提供される ProperyGrid コントロールは、ユーザー インターフェイスを強化するために使用できる豊富な編集エクスペリエンスを提供します。 PropertyGrid をカスタマイズする簡単な方法に関する新しい知識があれば、アプリケーション全体で PropertyGrid を使用することになります。 さらに、Visual Studio .NET プロパティ ブラウザーは PropertyGrid に基づいているため、これらの手法を使用して、より豊富なデザイン時間エクスペリエンスを提供できます。