Пользовательский UITypeEditor на панели ActionList / Smart Tag - PullRequest
0 голосов
/ 25 августа 2011

У меня есть пользовательский UserControl со свойством ParentNode типа OptionsNode, которое наследует TreeNode. Мой элемент управления содержит TreeView, в котором многие из этих узлов отображаются во время разработки. Предполагается, что свойство ParentNode позволяет пользователю выбрать один из узлов в TreeView, подобно тому, как можно выбрать компоненты из раскрывающегося списка в сетке свойств, затем в раскрывающемся списке отображаются все доступные компоненты. Например, свойство AcceptButton любой формы отображает раскрывающийся список со всеми кнопками в форме на выбор.

Чтобы получить такое поведение в сетке свойств, я написал пользовательский UITypeEditor для класса OptionsNode. Это говорит сетке свойств для отображения выпадающего списка, и в этом раскрывающемся списке я добавляю ListBox, который заполнен списком всех узлов в TreeView. Это прекрасно работает, пользователь может раскрыть «свойство» и выбрать узел, просто щелкнув по нему.

Теперь, после некоторой дополнительной работы, я реализовал собственный ControlDesigner, а также ActionList, иногда называемый панелью Smart Tag. Я говорю о небольшом всплывающем окне с общими свойствами / дизайнерских методах, которое появляется, когда вы нажимаете кнопку [>] в правом верхнем углу некоторых элементов управления (например, TabControl позволяет вам добавлять / удалять вкладки оттуда).

Я все делал это раньше, и он работает нормально. Проблема в том, что я хочу показать это же свойство ParentNode на панели ActionList. Итак, класс DesignerActionList имеет «свойство proxy», которое проходит через значение свойства из 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 просто показывает TextBox вместо моего пользовательского UITypeEditor на панели смарт-тегов.

Я прочел еще кое-что в статье, которую я связал ранее (http://msdn.microsoft.com/en-us/magazine/cc163758.aspx#S3), и он специально решает эту проблему. Его элемент управления Clock имеет свойство Face с FaceEditor UITypeEditor, который позволяет людям графически выбирать циферблат часов (цифровой, аналоговый или оба) через раскрывающийся список.

Его решение состоит в том, чтобы просто декорировать свойство proxy с помощью атрибута Editor, так же как и в исходном свойстве Face.

Хорошо, я попробовал это:

    <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 - это ActionList в OptionsPanelDesigner, конструкторе для элемента управления OptionsPanel), но я не вижу, насколько он здесь уместен. Я нигде не кастую, но, видимо, код делает это где-то за кулисами.

Чего мне не хватает? Почему мой редактор выдает ошибки при попытке использовать пользовательский UITypeEditor, а в статье говорится, что он должен работать?

Спасибо!

1 Ответ

0 голосов
/ 26 августа 2011

Я решил это сам.

Проблема действительно была приведена к 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. Поэтому теперь я сначала пытаюсь привести Instance к OptionsPanel, и если это не удается, я предполагаю, что это класс ActionList и использую его свойство Host (или Control) для получения OptionsPanel.

Кажется, до сих пор работает!

...