Подтвердить что ты не робот

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

Как вы изменяете свойствоgrid во время выполнения во всех отношениях? Я хочу иметь возможность добавлять и удалять свойства и добавлять "динамические типы", что я имею в виду под этим - это тип, который приводит к выпадающему списку среды выполнения с помощью 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 или перечисления, но когда я пытаюсь добавить "динамический тип", например StateList, он не работает. Кто-нибудь знает, почему и может помочь мне решить эту проблему?

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

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

4b9b3361

Ответ 1

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

Ответ 2

Ах, конечно!

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

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

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

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

Ответ 3

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

Сначала я добавил параметр 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 ​​в моем классе динамического типа (например, StateList), чтобы использовать новое свойство 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);

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

Ответ 4

в моем случае 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;
    }
}