0

TreeNode を継承するタイプ OptionsNode の ParentNode というプロパティを持つカスタム UserControl があります。私のコントロールには、設計時にこれらのノードの多くが表示される TreeView が含まれています。ParentNode プロパティは、ユーザーが TreeView 内のノードの 1 つを選択できるようにすることを想定しています。これは、プロパティ グリッドのドロップダウンからコンポーネントを選択する方法と同様に、ドロップダウンに使用可能なすべてのコンポーネントが表示されます。たとえば、任意のフォームの AcceptButton プロパティは、フォーム上のすべてのボタンから選択できるドロップダウンを表示します。

プロパティ グリッドでこの動作を実現するために、OptionsNode クラスのカスタム UITypeEditor を作成しました。これにより、ドロップダウンを表示するようにプロパティ グリッドに指示され、このドロップダウンに、TreeView 内のすべてのノードのリストで埋められる ListBox を追加します。これは問題なく機能します。ユーザーは「プロパティ」をドロップダウンし、クリックするだけでノードを選択できます。

ここで、さらに作業を行った後、カスタム ControlDesigner と、スマート タグ パネルと呼ばれることもある ActionList を実装しました。一部のコントロールの右上にある [>] ボタンをクリックするとポップアップする一般的なプロパティ/デザイナー メソッドを含む小さなポップアップについて話しています (たとえば、TabControl を使用すると、そこからタブページを追加/削除できます)。

私はこれをすべて以前に行ったことがありますが、うまく機能しています。ここでの問題は、ActionList パネルに同じ ParentNode プロパティを表示したいということです。そのため、DesignerActionList クラスには、プロパティ値を ActionList からコントロールに、またはその逆に渡す「プロキシ プロパティ」があります。これは、ドキュメントとこの記事で説明されているとおりです: http://msdn.microsoft.com/ en-us/magazine/cc163758.aspx#S3

コード:

Friend Class OptionsPanelActionList
    Inherits DesignerActionList

    Public Sub New(ByVal host As OptionsPanel)
        MyBase.New(host)
    End Sub

    Public Property ParentNode As OptionsNode
        Get
            Return Me.Host.ParentNode
        End Get
        Set(value As OptionsNode)                 
            Me.SetProperty("ParentNode", value)                 
            Me.DesignerActionService.Refresh(Me.Host)
        End Set
    End Property

    Public Overrides Function GetSortedActionItems() As DesignerActionItemCollection
        Dim items As New DesignerActionItemCollection

        items.Add(New DesignerActionPropertyItem("ParentNode", "Parent node:", String.Empty, "Gets or sets the parent node."))

        Return items
    End Function

End Class

ただし、これは機能しません。ActionList は、スマート タグ パネルでカスタム UITypeEditor の代わりに TextBox を表示するだけです。

以前にリンクした記事 (http://msdn.microsoft.com/en-us/magazine/cc163758.aspx#S3) を読んだところ、彼は具体的にこの問題について詳しく説明しています。彼のクロック コントロールには、FaceEditor UITypeEditor を持つ Face プロパティがあり、ユーザーはドロップダウンからクロック フェイス (デジタル、アナログ、またはその両方) をグラフィカルに選択できます。

彼の解決策は、元の Face プロパティと同じように、プロキシ プロパティを Editor 属性で単純に装飾することです。

わかりました、それで私はそれを試しました:

    <Editor(GetType(Editors.OptionsNodeEditor), GetType(UITypeEditor))> _
    Public Property ParentNode As OptionsNode
        Get
            Return Me.Host.ParentNode
        End Get
        Set(value As OptionsNode)                 
            Me.SetProperty("ParentNode", value)                 
            Me.DesignerActionService.Refresh(Me.Host)
        End Set
    End Property

アクション リスト ウィンドウを開くと、TextBox ではなくドロップダウン スタイルが表示されます。すごい!しかし、ドロップダウンを開こうとするとすぐに、「ドロップダウンの使用中にエラーが発生しました: タイプ 'OptionsPanelActionList' のオブジェクトをタイプ 'OptionsPanel' にキャストできません」というエラーが表示されます。

このエラーがわかりません。OptionsPanelActionList オブジェクトを OptionsPanel にキャストしようとしているようです。OptionsPanel は、私が設計しているコントロールです (OptionsPanelActionList は、OptionsPanel コントロールのデザイナーである OptionsPanelDesigner の ActionList です) が、ここでの関連性がわかりません。私はどこにもキャストしていませんが、コードはどこかで舞台裏でこれを行っているようです。

私は何が欠けていますか?カスタム UITypeEditor を使用しようとすると、エディターがエラーをスローするのはなぜですか?

ありがとう!

4

1 に答える 1

0

私はそれを自分で解決しました。

問題は実際に OptionsPanel へのキャストでした。カスタム UITypeEditor で発生します。編集中のコントロール (OptionsPanel) への参照が必要ですが、context.Instance プロパティを介して取得できることがわかりました。

Public Overrides Function EditValue(context As System.ComponentModel.ITypeDescriptorContext, provider As System.IServiceProvider, value As Object) As Object
    Dim panel As OptionsPanel = DirectCast(context.Instance, OptionsPanel)
    '...
End Function

どうやら、ActionList / Smart Tag ウィンドウを介してプロパティを編集する場合、context.Instance オブジェクトはパネルではなく、ActionList クラスのインスタンスです。そこで、最初にインスタンスを OptionsPanel にキャストしようとします。それが失敗した場合は、それが ActionList クラスであると想定し、その Host (または Control) プロパティを使用して OptionsPanel を取得します。

これまでのところうまくいくようです!

于 2011-08-26T06:56:01.130 に答える