Просмотр и редактирование подчиненного свойства свойства в PropertyGrid
Я больше не мог найти точное решение моей проблемы в Интернете, поэтому я задаю этот вопрос. Надеюсь, ты сможешь мне помочь.
У меня есть следующие классы:
public Item
{
public FieldType MyField { get; set; }
public string Description { get; set; }
public int Capacity { get; set; }
}
public FieldType
{
public string Value { get; set; }
public string FieldCode { get; set; }
public string TableCode { get; set; }
}
В своей форме я создал экземпляр класса Item. Который содержит следующие члены:
- MyField (тип FieldType)
- Описание (тип строки)
- Емкость (целое)
Можно ли показать только Value
член MyField
недвижимость в PropertyGrid
?
Ниже показано, как назначить свойство выбранного объекта PropertyGrid
,
void Form1(object sender, EventArgs e)
{
propertyGrid1.SelectedObject = new Item();
}
3 ответа
Да легко
добавить вычисляемое свойство только для чтения в Item
public Item
{
public FieldType MyField { get; set; }
public string MyFieldValue => MyField.Value;
public string Description { get; set; }
public int Capacity { get; set; }
}
Решение 1 - Добавить свойство
Вы можете добавить свойство к Item
класс, чтобы получить и установить MyField.Value
:
public string Value
{
get
{
if (MyField != null)
return MyField.Value;
return null;
}
set
{
if (MyField != null)
MyField.Value = value;
}
}
• Предпочтительно определять это свойство в частичном классе.
• Используйте эту опцию, когда у вас есть доступ к кодам классов. Если эти классы не ваши, используйте 3-е решение.
Решение 2 - Используйте ExpandableObjectConverter
Вы можете украсить MyField
собственностью Item
класс с ExpandableObjectConverter
, Также украсить FieldType
с [Browsable(false)]
из FieldType
класс, чтобы скрыть его в сетке свойств, если вы хотите:
[TypeConverter(typeof(ExpandableObjectConverter))]
public FieldType MyField { get; set; }
• Чтобы настроить текст, который отображается перед MyField
Вы можете переопределить ToString
метод FieldType
и вернуться Value
, Также вы можете сделать это с помощью пользовательских TypeConverter
и переопределив его ConvertTo
метод.
Решение 3. Используйте пользовательский TypeDescriptor
Это не так просто, как первое решение, но результат полностью совпадает с тем, что вы получаете, используя первое решение. Это подходит для случаев, когда вы не можете манипулировать этими классами.
Вы можете использовать это так:
var item = new Item() { MyField = new FieldType() { Value = "Some Value" } };
TypeDescriptor.AddProvider(new MyTypeDescriptionProvider(), item);
this.propertyGrid1.SelectedObject = item;
Или украшая Item
класс с:
[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]
public class Item
Пользовательский дескриптор свойства
public class MyPropertyDescriptor : PropertyDescriptor
{
private PropertyDescriptor subProperty;
private PropertyDescriptor parentProperty;
public MyPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor sub)
: base(sub, null)
{
subProperty = sub;
parentProperty = parent;
}
public override bool IsReadOnly { get { return subProperty.IsReadOnly; } }
public override void ResetValue(object component)
{
subProperty.ResetValue(parentProperty.GetValue(component));
}
public override bool CanResetValue(object component)
{
return subProperty.CanResetValue(parentProperty.GetValue(component));
}
public override bool ShouldSerializeValue(object component)
{
return subProperty.ShouldSerializeValue(parentProperty.GetValue(component));
}
public override Type ComponentType { get { return parentProperty.ComponentType; } }
public override Type PropertyType { get { return subProperty.PropertyType; } }
public override object GetValue(object component)
{
return subProperty.GetValue(parentProperty.GetValue(component));
}
public override void SetValue(object component, object value)
{
subProperty.SetValue(parentProperty.GetValue(component), value);
OnValueChanged(component, EventArgs.Empty);
}
}
Пользовательский тип Дескриптор
public class MyTypeDescriptor : CustomTypeDescriptor
{
ICustomTypeDescriptor original;
public MyTypeDescriptor(ICustomTypeDescriptor originalDescriptor)
: base(originalDescriptor)
{
original = originalDescriptor;
}
public override PropertyDescriptorCollection GetProperties()
{
return this.GetProperties(new Attribute[] { });
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var properties = original.GetProperties().Cast<PropertyDescriptor>().ToList();
var parent = properties.Where(x => x.Name == "MyField").First();
var sub = TypeDescriptor.GetProperties(typeof(FieldType))["Value"];
properties.Remove(parent);
properties.Add(new MyPropertyDescriptor(parent, sub));
return new PropertyDescriptorCollection(properties.ToArray());
}
}
Пользовательский TypeDescriptorProvider
public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
public MyTypeDescriptionProvider()
: base(TypeDescriptor.GetProvider(typeof(object))) { }
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
object instance)
{
ICustomTypeDescriptor baseDes = base.GetTypeDescriptor(objectType, instance);
return new MyTypeDescriptor(baseDes);
}
}
• Используйте эту опцию, если Item
а также FieldType
не твои. Если эти классы принадлежат вам, и вы можете изменить их код, используйте первое решение.
Я не совсем уверен, что вы ищете, но вот 2 ответа
1.(как я понял)
если вы хотите, чтобы он показывал только Value
когда вы пытаетесь просмотреть свойства MyField
После этого все, что вам нужно сделать, это добавить конструктор к MyField
так что вы можете назначить два других значения и изменить открытое свойство на private
вот так
public FieldType
{
public string Value { get; set; }
private string FieldCode { get; set; }
private string TableCode { get; set; }
}
2.(это скроет MyField
из вашей недвижимости Grid)
Переопределить ToString()
метод FielType
вот так
public override string ToString()
{
return Value;
}
затем установите ваш MyField
в частном порядке и инкапсулировать его. возвращая экземпляр в виде строки. который будет использовать переопределенное значение. вот так
private FieldType MyField;
public string value{ get{return MyField.ToString();}set;}
ваш MyField вернет переопределенный ToString
значение, которое возвращает значение.