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

StackOverflow https://stackoverflow.com/questions/313822

Вопрос

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

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

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

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

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

Это было полезно?

Решение

Что вы делаете, так это добавляете StatesList (TypeConverter) в качестве свойства.
Что вам следует сделать, так это добавить свойство с помощью StatesList в качестве преобразователя типов.

Другие советы

Ах, конечно!

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

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

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

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

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

Сначала я добавил параметр 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);

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

в моем случае 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;
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top