Сетка свойств .Net.Есть ли способ позволить сетке манипулировать объектом по-другому?
-
06-09-2019 - |
Вопрос
Как я понял, сетке свойств предоставляется объект, которым она может манипулировать, извлекая его свойства с помощью отражений.
Моя проблема в том, что у меня есть набор параметров, который определяется во время выполнения, поэтому я не могу статически составить класс со свойствами для представления этого набора.
У меня есть две идеи для решения этой проблемы, но обе они сложны и, вероятно, отнимут много времени, на самом деле я скажу, что они непрактичны в моих временных ограничениях.Один из них — использовать Reflection Emit для динамического определения класса, а другой — динамически создать исходный файл C# и затем скомпилировать его с помощью CodeDom.
Может ли сетка свойств вести себя по-другому (кроме извлечения свойств объекта с использованием отражений), что может решить мою проблему?
Если нет, знаете ли вы какой-либо другой элемент управления, который может выполнить эту работу за меня?
Я хочу сказать, что причина, по которой я с самого начала обратился к сетке свойств, заключалась в ее способности предоставлять действительно приятный пользовательский интерфейс извлечения данных для распространенных типов. Для цвета вы автоматически получаете палитру, для dataTime у вас автоматически есть хороший календарь.Я бы хотел получить эти вещи автоматически, если это возможно.
Решение
Да, 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
}}
});
}
}