PropertyGrid-动态加载下拉值 [英] PropertyGrid - Load dropdown values dynamically

查看:50
本文介绍了PropertyGrid-动态加载下拉值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了各种方法-与TypeConverters等产生了很多混乱.因此,在此我将不做所有介绍.

I've tried all sorts - lots of messing around with TypeConverters etc. So I won't cover all that here.

因此,将问题简化为基本问题.考虑以下内容:

So to reduce the question to its basics. Considering the below:

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

如何从mSystemTypes集合动态填充"SystemTypes"作为下拉选择器?例如.您选择控制台",它将使用匹配的mSystemType更新mSystem.

How do I get "SystemTypes" as a dropdown selector dynamically filled from a mSystemTypes collection? E.g. You select "Console" and it updates mSystem with the matching mSystemType.

我正在使用LiteDb,这可能会使事情变得有些困难,因为它不像其他情况下那样纯粹是外键"的整数,而是一个完整的对象.

I am using LiteDb, which may make things a little more difficult, as it isn't purely an integer for the 'foreign key' as other scenarios may present, but a full object.

我需要维护'dbRef'方法,以确保数据关系的完整性.以防万一DBLite东西掉进了曲线球,下面的一些代码演示了它的用法:

I need to maintain the 'dbRef' approach to ensure integrity of data relationships. Just in case the DBLite thing throws in a curve ball, some code below demonstrating its use:

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中使用它?),但是我敢肯定有一些解决方法.

LiteDb.LiteCollection doesn't map directly onto ICollection (you use this in TypeConverter?), but I'm sure there's some work around.

推荐答案

简而言之,您需要创建一个支持标准值的新 TypeConverter .

In short, you need to create a new TypeConverter supporting standard values.

示例-VB.NET

我想您有一个 Product 类,具有一个 Category 类型的属性,您希望能够从 List< Category> 中进行选择.code>在运行时来自数据库之类的地方:

I suppose you have a Product class, having a property of type Category which you want to be able to choose from a List<Category> which is coming from somewhere like database at run-time:

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 类,该类可以从任意位置加载类别:

And here is the CategoryService class which can load categories from wherever you like:

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 ,它负责为下拉菜单提供值:

The next step is creating CategoryConverter which is responsible to provide values for the dropdown:

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 属性,您可以从列表中选择一个值.

Then as a result, when you set an instance of Product as SelectedObject of the PropertyGrid, for Category property, you choose a value from list.

示例-C#

以下是上面示例的C#版本:

Here is the C# version of the above example:

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);
    }
}

这篇关于PropertyGrid-动态加载下拉值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆