【问题标题】:How to modify PropertyGrid at runtime (add/remove property and dynamic types/enums)如何在运行时修改 PropertyGrid(添加/删除属性和动态类型/枚举)
【发布时间】:2010-09-23 18:01:40
【问题描述】:

如何在运行时以各种方式修改属性网格?我希望能够添加和删除属性并添加“动态类型”,我的意思是这种类型会导致使用 TypeConverter 在 propertygrid 中生成运行时下拉列表。

我实际上已经能够做这两件事(添加/删除属性和添加动态类型),但不能同时做。

为了实现在运行时添加和删除属性的支持,我使用了this codeproject article 并稍微修改了代码以支持不同的类型(不仅仅是字符串)。

private System.Windows.Forms.PropertyGrid propertyGrid1;
private CustomClass myProperties = new CustomClass();

public Form1()
{
    InitializeComponent();

    myProperties.Add(new CustomProperty("Name", "Sven", typeof(string), false, true));
    myProperties.Add(new CustomProperty("MyBool", "True", typeof(bool), false, true));
    myProperties.Add(new CustomProperty("CaptionPosition", "Top", typeof(CaptionPosition), false, true));
    myProperties.Add(new CustomProperty("Custom", "", typeof(StatesList), false, true)); //<-- doesn't work
}

/// <summary>
/// CustomClass (Which is binding to property grid)
/// </summary>
public class CustomClass: CollectionBase,ICustomTypeDescriptor
{
    /// <summary>
    /// Add CustomProperty to Collectionbase List
    /// </summary>
    /// <param name="Value"></param>
    public void Add(CustomProperty Value)
    {
        base.List.Add(Value);
    }

    /// <summary>
    /// Remove item from List
    /// </summary>
    /// <param name="Name"></param>
    public void Remove(string Name)
    {
        foreach(CustomProperty prop in base.List)
        {
            if(prop.Name == Name)
            {
                base.List.Remove(prop);
                return;
            }
        }
    }

等等……

public enum CaptionPosition
{
    Top,
    Left
}

我的完整解决方案可以下载here

当我添加字符串、布尔值或枚举时,它可以正常工作,但是当我尝试添加像 StatesList 这样的“动态类型”时,它就不起作用了。有谁知道为什么,可以帮我解决吗?

public class StatesList : System.ComponentModel.StringConverter
{
    private string[] _States = { "Alabama", "Alaska", "Arizona", "Arkansas" };

    public override System.ComponentModel.TypeConverter.StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(_States);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }
}

当您不尝试在运行时添加属性时,使用 TypeConverter 的方法可以正常工作,例如 this code 可以正常工作,但我希望能够同时做到这两个。

请查看my project。 谢谢!

【问题讨论】:

    标签: c# .net winforms propertygrid


    【解决方案1】:

    您所做的是将StatesList(一个TypeConverter)添加为属性。
    您应该做的是添加一个以 StatesList 作为其 TypeConverter 的属性。

    【讨论】:

      【解决方案2】:

      啊,当然!

      myProperties.Add(new CustomProperty("Custom", "", typeof(States), false, true));
      
      [TypeConverter(typeof(StatesList))]
      public class States
      {
      }
      

      像魅力一样工作,谢谢!

      我已经更新了我的项目,希望对大家有帮助,可以找到here

      【讨论】:

      • 我知道这篇文章很老了,但我有一个简短的问题。我在我的应用程序中完全使用了您的代码,但自定义组合框不起作用。该属性的名称显示为灰色,并且没有可用选项。任何想法,我能做些什么来解决这个问题?在此先感谢马丁
      • @user653427,由于这是一个老问题,发布一个新问题并链接回此页面可能也是值得的。通过这种方式,您将能够提供更多细节并吸引更多人。
      • 为了避免额外的空“状态”类,您还可以在您的情况下在 PropertyDescriptor 实现(CustomPropertyDescriptor)中返回类型转换器 - 要覆盖的成员是:public TypeConverter Converter
      • 谢谢,如果用户从 CaptionPosition 组合框中选择顶部或底部我们如何在代码中获取该值?
      • 另一个问题是,当您为 CaptionPosition 枚举新建 CustomProperty 时,您将 "top" 设置为 value 。但是当我运行应用程序时,起初标题位置字段中没有“顶部”值。当我从该组合框中选择项目时,显示的相关值。我该如何解决这个问题?我的意思是为组合框定义默认值
      【解决方案3】:

      这个问题和答案对我很有用。但是,我需要通过允许运行时生成的下拉列表值来进一步扩展一些东西。我想我会发布一些关于它需要什么的示例代码,以防有人发现它有用。

      首先,我在 CustomProperty 构造函数中添加了一个 options 参数,并添加了一个 Options 属性:

          private List<string> lOptions;
      
          public CustomProperty(string sName, object value, Type tType, bool bReadOnly, bool bVisible, List<string> lOptions)
          {
              this.lOptions = lOptions;
          }
      
          public List<string> Options
          {
              get { return lOptions; }
          }
      

      其次,我在 CustomPropertyDescriptor 类中添加了一个 Options 属性:

          public List<string> Options
          {
              get
              {
                  return m_Property.Options;
              }
          }
      

      第三,我必须修改我的动态类型类(即 StatesList)中的 GetStandardValues 方法,以利用 CustomPropertyDescriptor 对象上的新 Options 属性:

          public override StandardValuesCollection
                       GetStandardValues(ITypeDescriptorContext context)
          {
              CustomPropertyDescriptor descriptor = (CustomPropertyDescriptor)context.PropertyDescriptor;
              return new StandardValuesCollection(descriptor.Options);
          }
      

      最后,我必须在创建新的 CustomProperty 对象时传入我的选项列表:

          List<string> optionsList = new List<string>(new string[] { "test1", "test2", "test3" });        
          CustomProperty myProperty = new CustomProperty(attr.Name, attr.Value, valueType, false, true, optionsList);
      

      代替我在此示例中传递的静态列表,您可以以任何您喜欢的方式为下拉菜单生成选项列表,让您完全控制可用选项。

      【讨论】:

      • 感谢您花时间扩展答案,非常有帮助。
      • 什么是 valueType ?它的 typeof(list) ?
      • 它是被传递的属性值的类型,可以是字符串、整数或像States 这样的自定义类型(参见@salle55 的回答)。您可以使用 typeof,就像您指出的那样,或者可能是 value.GetType()。
      【解决方案4】:

      就我而言,TypeConverter 不适用于 States 类

      [TypeConverter(typeof(StatesList))] // not work
      public class States
      {
      }
      

      所以我在 CustomPropertyDescriptor 中添加了覆盖

      public override TypeConverter Converter
      {
          get {
              if (this.PropertyType.Equals(typeof(States)) ) {
                  return new StatesList(); ; 
              }
              return base.Converter;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 2014-08-19
        • 1970-01-01
        • 2014-07-07
        • 1970-01-01
        • 2010-10-03
        • 1970-01-01
        • 1970-01-01
        • 2017-04-22
        相关资源
        最近更新 更多