PropertyGrid - 动态加载下拉值
PropertyGrid - Load dropdown values dynamically
我已经尝试了各种方法 - 大量使用 TypeConverters 等。所以我不会在这里介绍所有内容。
因此,将问题简化为基础知识。考虑以下因素:
Imports LiteDB
Imports System.ComponentModel
Public Class mSystem
<CategoryAttribute("General"), ReadOnlyAttribute(True)>
Public Property ID As Integer
Public Property ShortName As String = ""
<BsonRef("mSystemTypes")>
Public Property SystemType As mSystemType
End Class
Public Class mSystemType
<CategoryAttribute("General"), ReadOnlyAttribute(True)>
Public Property ID As Integer
Public Property Name As String = "Default"
Public Property Details As String = ""
End Class
如何获取 "SystemTypes" 作为下拉列表 select 或从 mSystemTypes 集合中动态填充?例如。您 select "Console" 并使用匹配的 mSystemType 更新 mSystem。
我正在使用 LiteDb,这可能会使事情变得有点困难,因为它不是 'foreign key' 的纯粹整数,就像其他情况下可能出现的那样,而是一个完整的对象。
我需要维护 'dbRef' 方法来确保数据关系的完整性。以防万一 DBLite 东西抛出曲线球,下面的一些代码演示了它的用法:
Public Class dbCollecitons
Public mSystems As LiteCollection(Of mSystem)
Public mSystemTypes As LiteCollection(Of mSystemType)
Private Sub Examples()
Dim col As LiteCollection(Of mSystemType) = dbCollections.mSystemTypes
Dim value as String = "Console"
Dim q = col.FindAll.Where(Function(x) x.Name = value).First
Console.Writeline(q.ID)
End Sub
End Class
LiteDb.LiteCollection 不直接映射到 ICollection(您在 TypeConverter 中使用它?),但我确信有一些解决方法。
简而言之,您需要创建一个新的TypeConverter
支持标准值。
示例 - VB.NET
我想你有一个 Product
class,有一个 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
class,它可以从任何你喜欢的地方加载类别:
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);
}
}
我已经尝试了各种方法 - 大量使用 TypeConverters 等。所以我不会在这里介绍所有内容。
因此,将问题简化为基础知识。考虑以下因素:
Imports LiteDB
Imports System.ComponentModel
Public Class mSystem
<CategoryAttribute("General"), ReadOnlyAttribute(True)>
Public Property ID As Integer
Public Property ShortName As String = ""
<BsonRef("mSystemTypes")>
Public Property SystemType As mSystemType
End Class
Public Class mSystemType
<CategoryAttribute("General"), ReadOnlyAttribute(True)>
Public Property ID As Integer
Public Property Name As String = "Default"
Public Property Details As String = ""
End Class
如何获取 "SystemTypes" 作为下拉列表 select 或从 mSystemTypes 集合中动态填充?例如。您 select "Console" 并使用匹配的 mSystemType 更新 mSystem。
我正在使用 LiteDb,这可能会使事情变得有点困难,因为它不是 'foreign key' 的纯粹整数,就像其他情况下可能出现的那样,而是一个完整的对象。
我需要维护 'dbRef' 方法来确保数据关系的完整性。以防万一 DBLite 东西抛出曲线球,下面的一些代码演示了它的用法:
Public Class dbCollecitons
Public mSystems As LiteCollection(Of mSystem)
Public mSystemTypes As LiteCollection(Of mSystemType)
Private Sub Examples()
Dim col As LiteCollection(Of mSystemType) = dbCollections.mSystemTypes
Dim value as String = "Console"
Dim q = col.FindAll.Where(Function(x) x.Name = value).First
Console.Writeline(q.ID)
End Sub
End Class
LiteDb.LiteCollection 不直接映射到 ICollection(您在 TypeConverter 中使用它?),但我确信有一些解决方法。
简而言之,您需要创建一个新的TypeConverter
支持标准值。
示例 - VB.NET
我想你有一个 Product
class,有一个 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
class,它可以从任何你喜欢的地方加载类别:
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);
}
}