2016-08-01 96 views
0

我无法再在Internet中找到我的问题的确切解决方案,因此我正在问这个问题。希望你能帮助我。在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; } 
} 

在我的形式,我创建项目类的一个实例。它包含以下成员:

  • MyField的(类型的FieldType的)
  • 描述(字符串类型)
  • 容量(一个int)

是否有可能只显示Value成员的MyField物业PropertyGrid

以下是我如何分配PropertyGrid的选定对象属性。

void Form1(object sender, EventArgs e) 
{ 
    propertyGrid1.SelectedObject = new Item();   
} 
+0

您可以通过创建包装来控制显示内容和显示方式。典型的应用是翻译所有的属性,隐藏一些,运行时切换等。但最基本的答案是使用'[Browsable(false)]'属性。 – Sinatr

回答

1

是的,很简单:
一个计算的只读属性添加到Item

public Item 
{ 
    public FieldType MyField { get; set; } 
    public string MyFieldValue => MyField.Value; 
    public string Description { get; set; } 
    public int Capacity { get; set; } 
} 
0

我不是真的知道你正在寻找的,但这里有2个答案

1(如我理解它)
如果你想它只显示Value当你试图查看一个MyField实例的属性,那么你所需要做的就是将一个构造函数添加到MyField所以您可以指定其他两个值和公共属性更改为private像这样

public FieldType 
{ 
    public string Value { get; set; } 
    private string FieldCode { get; set; } 
    private string TableCode { get; set; } 
} 


2.(这将隐藏您的PropertyGrid中的MyField
覆盖的FielTypeToString()方法,像这样

public override string ToString() 
{ 
    return Value; 
} 

然后将您的MyField设置为私有并封装它。以字符串形式返回实例。这将使用重写的值。 像这样

private FieldType MyField; 
public string value{ get{return MyField.ToString();}set;} 

您MyField的将返回重写ToString值返回值。

+0

'public string value {get {return MyField;} set;}' - 我认为这会导致编译时错误 – yonan2236

+0

@ yonan2236谢谢...修复它 – Neil

0

解决方案1 ​​ - 添加属性

您可以将属性添加到Item类来获取和设置MyField.Value

public string Value 
{ 
    get 
    { 
     if (MyField != null) 
      return MyField.Value; 
     return null; 
    } 
    set 
    { 
     if (MyField != null) 
      MyField.Value = value; 
    } 
} 

enter image description here

•最好定义一个部分,物业类。
•当您有权访问类的代码时使用此选项。如果这些课程不是你的,请使用第三种解决方案。

解决方案2 - 使用ExpandableObjectConverter

您可以ExpandableObjectConverter装饰Item类的MyField财产。另外随着[Browsable(false)]装饰FieldTypeFieldType类来隐藏它在属性网格中,如果你想:

[TypeConverter(typeof(ExpandableObjectConverter))] 
public FieldType MyField { get; set; } 

enter image description here

•要自定义其在MyField前面显示的文本,可以覆盖的FieldTypeToString方法并返回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); 
    } 
} 

•使用此选项,如果ItemFieldType是不是你的。如果这些类是您的,并且您可以更改其代码,请使用第一种解决方案。