从属性派生的PropertyGrid下拉列表是对象类,而不仅仅是字符串

问题描述 投票:0回答:2

我如何在属性网格中具有作为对象(不仅仅是字符串)下拉列表的属性?我到现在为止,但是随后被卡住了!考虑下面的代码:

Public Class mOrganisation

    Public Property ID as String
    Public Property Name as String

End Class

Public Class mSystem

    Public Property ID as string
    Public Property Name as String
    Public Property Developer as mOrganisation

     Public Overrides Function ToString() As String
        Return Name
    End Function

End Class

Public Class mGame

    Public Property ID as string
    Public Property Name as String

    <TypeConverter(GetType(SystemConverter))>
    Public Property System as mSystem

End Class

Public Class Main

    Public Systems as List(of mSystem) = [...list gatehring code here]

End Class


Public Class SystemConverter
Inherits TypeConverter

    Public Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overrides Function GetStandardValuesExclusive(ByVal context As ITypeDescriptorContext) As Boolean
        Return False
    End Function

    Public Overrides Function GetStandardValues(ByVal context As ITypeDescriptorContext) As TypeConverter.StandardValuesCollection
        Return New StandardValuesCollection(Main.Systems)
    End Function

End Class

mOrgnisation只是为了给mSystem类引入一些复杂性。现在,此代码确实删除了值:

enter image description here

但是当我选择一个值时,出现PropertyGrid错误“无法将类型为'System.String'的对象转换为类型为'mSystem'的”]

[这使我跌倒了一个兔子洞,特别是尝试应用Convert FromConvert To的各种排列。但是,我找不到合适的解决方案。一次通过ConvertFrom的尝试使下拉菜单加载非常缓慢,一次加载了一个项目(我认为每个项目都被触发了)。

我将创建一个自定义UITypeEditor,但是我找不到像标准下拉菜单那样获取PropertyGrid固有的调整大小方法/句柄的方法(并尝试编写自己的调整大小例程,但是由于以下原因,我觉得很粘而忽悠PropGrid +控件的交互)

实现此目的的最佳/最优雅的方法是什么?

.net propertygrid typeconverter uitypeeditor
2个回答
1
投票

有一些方法可以告诉系统“从物体中选择什么”

1)使用ComboBox上的DisplayMemberPath:

<ComboBox ItemsSource="{Binding Path=mSystem}" 
      DisplayMemberPath="Name"/>

2)在ComboBox上设置ItemTemplate。类似于#1,不同之处在于它允许您定义要显示的模板:

<ComboBox ItemsSource="{Binding Path=mSystem}">
<ComboBox.ItemTemplate>
    <DataTemplate>
        <Border BorderBrush="Green" BorderThickness="1" Padding="5">
            <TextBlock Text="{Binding Path=Name,StringFormat='Name: {0}'}" />
        </Border>
    </DataTemplate>
</ComboBox.ItemTemplate>

3)将数据模板添加到XAML资源。这对于关联给定的类很有用:

<UserControl xmlns:local="CLASS_CONTEXT_HERE">
<UserControl.Resources>
    <DataTemplate DataType="local:mSystem">
        <TextBlock Text="{Binding Name}" />
    </DataTemplate>
</UserControl.Resources>

4)如果要显示名称和ID:

Public Overrides Function ToString() As String
    Return string.Format("{0} ({1})", Name, ID)
End Function

0
投票

最终放弃了TypeConverter,并找到了解决方案。像大多数编码梦night一样,将5条简单的代码放置在正确的位置!关键是访问PropertyGrid内置的调整大小手柄。您可以调整以下代码,以包括构建处理自定义对象的过程,因为value是任何对象。但是,为简单起见,下面的示例是一个字符串:

Public Overrides ReadOnly Property IsDropDownResizable As Boolean
    Get
        Return True
    End Get
End Property

这里是实现方法:

第1步:创建新的UITypeEditor

这会将属性连接到自定义编辑器。值包含从属性传递的值。它可以是任何对象类型。因此,您可以将此传递给自定义控件,以通知其中的任何编辑功能。

创建新课程:

Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Windows.Forms.Design

Public Class TestUIEditor
    Inherits UITypeEditor

    ' Indicate that we display a dropdown.
    Public Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) _
        As UITypeEditorEditStyle

        Return UITypeEditorEditStyle.DropDown

    End Function

    Public Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object

        ' Get an IWindowsFormsEditorService object.
        Dim editor_service As IWindowsFormsEditorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
        If editor_service Is Nothing Then
            Return MyBase.EditValue(context, provider, value)
        End If

        'Setup the editor
        Dim editorService As IWindowsFormsEditorService = Nothing
        If provider IsNot Nothing Then
            editorService = TryCast(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
        End If

        If editorService IsNot Nothing Then

            Dim testUI As New TestPropGridUI(editorService)
            'Populate the existing value to the dropdown control
            testUI.Text = value
            'Drop down the control
            editorService.DropDownControl(testUI)
            'Update property value once dropdown closed
            value = testUI.Text

        End If

        Return value

    End Function

    Public Overrides ReadOnly Property IsDropDownResizable As Boolean
        Get
            'Ensures control is resizable
            Return True
        End Get
    End Property

End Class

第2步:创建自定义编辑器:

在此示例中,我只使用了一个继承TextBox的自定义类。但是,您可以使用任何控件,甚至可以使用自定义的UserControl。

Imports System.Windows.Forms.Design

Public Class TestPropGridUI
    Inherits TextBox

    ' The editor service displaying this control.
    Private m_EditorService As IWindowsFormsEditorService

    Public Sub New(ByVal editor_service As IWindowsFormsEditorService)
        MyBase.New()

        m_EditorService = editor_service
        Dock = DockStyle.Fill

    End Sub

    Public Sub returnPressed(sender As Object, e As KeyEventArgs) Handles Me.KeyDown

        'Closes the dropdown when Enter pressed
        If e.KeyCode = Keys.Enter Then
            m_EditorService.CloseDropDown()
        End If

    End Sub

End Class

注意m_EditorService.CloseDropDown。将其放在您希望下拉菜单自行关闭的任何位置(例如,选择值之后)。

第3步:告诉您的类属性使用自定义编辑器:

Public Class TestObject

    Public Property ID as String
    Public Property Quantity as Integer

    <Editor(GetType(TestUIEditor), GetType(UITypeEditor))>
    Public Property TestText As String

End Class

就这样!

© www.soinside.com 2019 - 2024. All rights reserved.