Как изменить PropertyGrid во время выполнения (добавить / удалить свойство и динамические типы / перечисления) - PullRequest
24 голосов
/ 24 ноября 2008

Как вы изменяете сетку свойств во время выполнения всеми способами? Я хочу иметь возможность добавлять и удалять свойства и добавлять «динамические типы», что я имею в виду под типом, который приводит к выпадающему сгенерированному во время выполнения раскрывающемуся списку свойств с использованием TypeConverter.

Я действительно смог сделать обе эти вещи (добавить / удалить свойства и добавить динамический тип), но только по отдельности, но не одновременно.

Для реализации поддержки добавления и удаления свойств во время выполнения я использовал эту статью проекта кода и немного изменил код для поддержки различных типов (не только строк).

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
}

Мое полное решение можно скачать здесь .

Он отлично работает, когда я добавляю строки, bools или перечисления, но когда я пытаюсь добавить «динамический тип», такой как 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 прекрасно работает, когда вы не пытаетесь добавить свойство во время выполнения, например, этот код работает без каких-либо проблем, но я хочу иметь возможность выполнять оба действия.

Пожалуйста, посмотрите на мой проект . Спасибо!

Ответы [ 4 ]

8 голосов
/ 24 ноября 2008

Что вы делаете, это добавление StatesList (TypeConverter) в качестве свойства.
Что вы должны сделать, это добавить свойство с StatesList в качестве TypeConverter.

5 голосов
/ 24 ноября 2008

Ах, конечно!

myProperties.Add(new CustomProperty("Custom", "", typeof(States), false, true));

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

Работает как шарм, спасибо!

Я обновил свой проект, надеюсь, он будет полезен другим, его можно найти здесь .

4 голосов
/ 03 августа 2011

Этот вопрос и ответ были очень полезны для меня. Тем не менее, мне нужно было еще кое-что расширить, допуская сгенерированные значения выпадающего списка во время выполнения. Я думал, что выложу некоторый пример кода относительно того, что он требует, на случай, если кто-то посчитает его полезным.

Сначала я добавил параметр options в конструктор CustomProperty и добавил свойство 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; }
    }

Во-вторых, я добавил свойство Options в класс CustomPropertyDescriptor:

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

В-третьих, мне пришлось изменить метод GetStandardValues ​​в моем классе динамического типа (например, StatesList), чтобы использовать новое свойство Options объекта CustomPropertyDescriptor:

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

Вместо статического списка, который я передал для этого примера, вы можете сгенерировать список опций для вашего выпадающего меню любым удобным для вас способом, предоставив вам полный контроль над доступными опциями.

0 голосов
/ 26 апреля 2017

в моем случае TypeConverter не применяется к классам состояний

[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;
    }
}
...