Просмотр и редактирование подчиненного свойства свойства в 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 значение, которое возвращает значение.

Другие вопросы по тегам