.Net Property Grid. Есть ли способ позволить Grid манипулировать объектом по-другому? - PullRequest
1 голос
/ 31 мая 2009

Как я понял, сетке свойств задается объект, которым он может манипулировать, извлекая свои свойства с помощью отражений.

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

У меня есть две идеи для решения этой проблемы, но обе они сложны и, вероятно, будут занимать много времени. На самом деле, я скажу, что они не практичны в моих временных рамках. Одним из них является использование Reflection Emit для динамического определения класса, а другим - динамическая сборка исходного файла C #, а затем его компиляция с использованием CodeDom.

Может ли сетка свойств вести себя по-другому (кроме извлечения свойств объекта с помощью отражений), что может удовлетворить мою проблему?

Если нет, знаете ли вы какой-либо другой элемент управления, который может выполнить эту работу за меня?

Я хочу сказать, что причиной, по которой я пошел к сетке свойств с самого начала, была ее способность предоставлять действительно хороший интерфейс для извлечения данных для распространенных типов. Для цвета вы автоматически получаете палитру. Для dataTime у вас автоматически есть хороший календарь. Я хотел бы получить эти вещи автоматически, если это возможно.

1 Ответ

5 голосов
/ 31 мая 2009

Да, PropertyGrid может отображать вещи , отличные , а не только свойства времени компиляции, используя любое из TypeConverter, ICustomTypeDescriptor или TypeDescriptionProvider для предоставления псевдо-свойств времени выполнения. Можете ли вы привести пример того, как выглядят ваши параметры? Я должен быть в состоянии привести пример ...


вот базовый пример (все string и т. Д.), Основанный на более раннем ответе (связан, но отличается):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
class PropertyBagPropertyDescriptor : PropertyDescriptor {
    public PropertyBagPropertyDescriptor(string name) : base(name, null) { }
    public override object GetValue(object component) {
        return ((PropertyBag)component)[Name];
    }
    public override void SetValue(object component, object value) {
        ((PropertyBag)component)[Name] = (string)value;
    }
    public override void ResetValue(object component) {
        ((PropertyBag)component)[Name] = null;
    }
    public override bool CanResetValue(object component) {
        return true;
    }
    public override bool ShouldSerializeValue(object component)
    { // *** this controls whether it appears bold or not; you could compare
      // *** to a default value, or the last saved value...
        return ((PropertyBag)component)[Name] != null;
    }
    public override Type PropertyType {
        get { return typeof(string); }
    }
    public override bool IsReadOnly {
        get { return false; }
    }
    public override Type ComponentType {
        get { return typeof(PropertyBag); }
    }
}
[TypeConverter(typeof(PropertyBagConverter))]
class PropertyBag {
    public string[] GetKeys() {
        string[] keys = new string[values.Keys.Count];
        values.Keys.CopyTo(keys, 0);
        Array.Sort(keys);
        return keys;
    }
    private readonly Dictionary<string, string> values
        = new Dictionary<string, string>();
    public string this[string key] {
        get {
            string value;
            values.TryGetValue(key, out value);
            return value;
        }
        set {
            if (value == null) values.Remove(key);
            else values[key] = value;
        }
    }
}
// has the job of (among other things) providing properties to the PropertyGrid
class PropertyBagConverter : TypeConverter {
    public override bool GetPropertiesSupported(ITypeDescriptorContext context) {
        return true; // are we providing custom properties from here?
    }
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, System.Attribute[] attributes) {
        // get the pseudo-properties
        PropertyBag bag = (PropertyBag)value;
        string[] keys = bag.GetKeys();
        PropertyDescriptor[] props = Array.ConvertAll(
            keys, key => new PropertyBagPropertyDescriptor(key));
        return new PropertyDescriptorCollection(props, true);
    }
}

static class Program {
    [STAThread]
    static void Main() { // demo form app
        PropertyBag bag = new PropertyBag();
        bag["abc"] = "def";
        bag["ghi"] = "jkl";
        bag["mno"] = "pqr";
        Application.EnableVisualStyles();
        Application.Run(
            new Form {
                Controls = { new PropertyGrid {
                    Dock = DockStyle.Fill,
                    SelectedObject = bag
                }}
            });
    }
}
...