简而言之,您需要创建一个新的TypeConverter 支持标准值。
示例 - VB.NET
我想你有一个Product 类,有一个Category 类型的属性,你希望能够从List<Category> 中进行选择,它在运行时来自数据库之类的地方:
Public Class Product
Public Property Id As Integer
Public Property Name As String
<TypeConverter(GetType(CategoryConverter))>
Public Property Category As Category
End Class
Public Class Category
Public Property Id As Integer
Public Property Name As String
Public Overrides Function ToString() As String
Return $"{Id} - {Name}"
End Function
End Class
这里是CategoryService 类,它可以从任何你喜欢的地方加载类别:
Public Class CategoryService
Private list As List(Of Category) = New List(Of Category) From {
New Category() With {.Id = 1, .Name = "Category 1"},
New Category() With {.Id = 2, .Name = "Category 2"},
New Category() With {.Id = 3, .Name = "Category 3"}
}
Public Function GetAll() As IEnumerable(Of Category)
Return list
End Function
End Class
下一步是创建CategoryConverter,它负责为下拉菜单提供值:
Imports System.ComponentModel
Public Class CategoryConverter
Inherits TypeConverter
Public Overrides Function GetStandardValues(ByVal context As ITypeDescriptorContext) As StandardValuesCollection
Dim svc = New CategoryService()
Return New StandardValuesCollection(svc.GetAll().ToList())
End Function
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 True
End Function
Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
If sourceType = GetType(String) Then Return True
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
If value IsNot Nothing AndAlso value.[GetType]() = GetType(String) Then
Dim v = $"{value}"
Dim id = Integer.Parse(v.Split("-"c)(0).Trim())
Dim svc = New CategoryService()
Return svc.GetAll().Where(Function(x) x.Id = id).FirstOrDefault()
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
End Class
因此,当您将Product 的实例设置为PropertyGrid 的SelectedObject 时,对于Category 属性,您从列表中选择一个值。
示例 - C#
这是上面例子的 C# 版本:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
[TypeConverter(typeof(CategoryConverter))]
public Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return $"{Id} - {Name}";
}
}
public class CategoryService
{
List<Category> list = new List<Category>{
new Category() { Id = 1, Name = "Category 1" },
new Category() { Id = 2, Name = "Category 2" },
new Category() { Id = 3, Name = "Category 3" },
};
public IEnumerable<Category> GetAll()
{
return list;
}
}
public class CategoryConverter : TypeConverter
{
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var svc = new CategoryService();
return new StandardValuesCollection(svc.GetAll().ToList());
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value != null && value.GetType() == typeof(string))
{
var v = $"{value}";
var id = int.Parse(v.Split('-')[0].Trim());
var svc = new CategoryService();
return svc.GetAll().Where(x => x.Id == id).FirstOrDefault();
}
return base.ConvertFrom(context, culture, value);
}
}