PropertyGrid - 根据另一个属性值更改下拉属性编辑器的项目

2023-12-07

我正在尝试在自定义组件中实现下拉属性,并且我使用了这个答案 and 这个答案作为指导。

到目前为止,我设法让它工作,并在下拉列表中使用预定义的项目。
但我仍然需要弄清楚如何更改下拉列表中的项目?

这是我到目前为止的代码(从上面提到的链接构建)

[TypeConverter(typeof(TableNameConverter))]
public TableName gttTableName
{ get; set; }

...

public class TableName
{
    public string Name { get; set; }

    public override string ToString()
    {
        return $"{Name}";
    }
}

public class TableNameService
{
    List<TableName> list = new List<TableName>() {
        new TableName() {Name = "naam 1" },
        new TableName() {Name = "naam 2" },
    };

    public IEnumerable<TableName> GetAll()
    {
        return list;
    }
}

public class TableNameConverter : TypeConverter
{
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        var svc = new TableNameService();
        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 name = v.ToString();
            var svc = new TableNameService();
            //return svc.GetAll().Where(x => x.Id == id).FirstOrDefault();
            return svc.GetAll().Where(x => x.Name == name).FirstOrDefault();
        }
        return base.ConvertFrom(context, culture, value);
    }
}

这在 VS 属性窗口中看起来像这样

enter image description here

现在的问题是,当某个属性发生变化时,下拉属性中的项目也必须发生变化。这应该在方法中完成UpdateTableNames(代码如下)。
换句话说,在另一个属性的设置器中,项目naam 1, naam 2可以更改为一套全新的套装,其中包含更多或更少的项目以及不同的值。
我还不知道如何更改这些项目?

让我解释一下情况。

  • 用户将自定义组件放到表单上
  • 当他查看属性 gttTableName 时,它​​现在会显示naam 1 and naam 2
  • 现在,用户更改另一个属性 (gttDataModule),并且在该属性的设置器中,gttTableName 属性的项目可以更改。
  • 因此,如果他再次查看属性 gttTableName,它现在应该显示完整的其他值列表。

属性 gttDataModule 的代码是这样的

public gttDataModule gttDataModule
{
    get { return _gttDataModule; }
    set
    {
        _gttDataModule = value;
        UpdateTableNames();
    }
}

private void UpdateTableNames()
{
    List<string> tableNames = new List<string>();
    if (_gttDataModule != null)
    {
        foreach (gttDataTable table in _gttDataModule.gttDataTables)
        {
            tableNames.Add(table.Table.TableName);
        }
    }

    // at this point the list tableNames will be populated with values.
    // What I need is to replace the list in TableNameService from 'naam 1', 'naam 2' 
    // to the values in this list.
    // so they won't be 'naam 1' and 'naam 2' anymore 
    // It could be more or less items or even none 
    // They could have different values
    // for example the list could be 'tblBox', 'tblUser', tblClient', tblOrders'
    // or it could be empty
    // or it could be 'vwCars', 'tblSettings'
}

我怎样才能改变里面的项目list of the TableNameService ?


我将根据这篇文章中的答案创建一个示例:PropertyGrid - 动态加载下拉值.

基本思想是拥有自定义类型转换器和重写获取标准值返回编辑属性支持的值的列表。

这里的要点是使用上下文实例获取正在编辑的对象的实例,并尝试根据编辑对象的其他属性过滤列表。

在下面的示例中,我将编辑Product其中有一个Category and a SubCategory属性,并且类别和子类别之间存在关系。例如,如果您选择类别 1,则子类别列表应显示类别 1 的子类别,但如果您选择类别 2,则列表应显示另一组子类别,如下所示:

enter image description here

这是示例的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    private Category category;
    [TypeConverter(typeof(CategoryConverter))]
    public Category Category
    {
        get { return category; }
        set
        {
            if (category?.Id != value?.Id)
            {
                category = value;
                SubCategory = null;
            }
        }
    }
    [TypeConverter(typeof(SubCategoryConverter))]
    public SubCategory SubCategory { get; set; }
}
public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return $"{Id} - {Name}";
    }
}
public class SubCategory
{
    public int Id { get; set; }
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return $"{Id} - {Name}";
    }
}
public class CategoryService
{
    List<Category> categories = new List<Category> {
        new Category() { Id = 1, Name = "Category 1" },
        new Category() { Id = 2, Name = "Category 2" },
    };
    List<SubCategory> subCategories = new List<SubCategory> {
        new SubCategory() { Id = 11, Name = "Sub Category 1-1", CategoryId= 1 },
        new SubCategory() { Id = 12, Name = "Sub Category 1-2", CategoryId= 1 },
        new SubCategory() { Id = 13, Name = "Sub Category 1-3", CategoryId= 1 },
        new SubCategory() { Id = 21, Name = "Sub Category 2-1", CategoryId= 2 },
        new SubCategory() { Id = 22, Name = "Sub Category 2-2", CategoryId= 2 },
    };
    public IEnumerable<Category> GetCategories()
    {
        return categories;
    }
    public IEnumerable<SubCategory> GetSubCategories()
    {
        return subCategories.ToList();
    }
}
public class CategoryConverter : TypeConverter
{
    public override StandardValuesCollection GetStandardValues(
        ITypeDescriptorContext context)
    {
        var svc = new CategoryService();
        return new StandardValuesCollection(svc.GetCategories().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.GetCategories()
                .Where(x => x.Id == id).FirstOrDefault();
        }
        return base.ConvertFrom(context, culture, value);
    }
}
public class SubCategoryConverter : TypeConverter
{
    public override StandardValuesCollection GetStandardValues(
        ITypeDescriptorContext context)
    {
        var svc = new CategoryService();
        var categoryId = ((Product)context.Instance).Category.Id;
        return new StandardValuesCollection(svc.GetSubCategories()
            .Where(x => x.CategoryId == categoryId).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.GetSubCategories()
                .Where(x => x.Id == id).FirstOrDefault();
        }
        return base.ConvertFrom(context, culture, value);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PropertyGrid - 根据另一个属性值更改下拉属性编辑器的项目 的相关文章

  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 如何在.NET Core上直接调用F#编译器?

    UPD 我想直接从 NET Core SDK 调用 F 编译器 即 fsc 我了解 dotnet build co 但当我只需要编译一个简单的问题时 即 fsc file fs 就足够的情况下 我不想涉及它们 我尝试在 NET Core S
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐