4

我有一個實現ICustomTypeDescriptor的類,它由用戶在PropertyGrid中查看和編輯。我的課程還有一個IsReadOnly屬性,用於確定用戶是否可以稍後保存更改。如果用戶無法保存,我不想讓用戶進行更改。因此,如果IsReadOnly爲true,我想重寫任何屬性,否則這些屬性可以在屬性網格中以只讀方式編輯。將ICustomTypeDescriptor.GetProperties返回的屬性動態更改爲只讀

我想使用ICustomTypeDescriptor的GetProperties方法來爲每個PropertyDescriptor添加一個ReadOnlyAttribute。但它似乎並沒有工作。這是我的代碼。

public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
{ 
    List<PropertyDescriptor> fullList = new List<PropertyDescriptor>(); 

    //gets the base properties (omits custom properties) 
    PropertyDescriptorCollection defaultProperties = TypeDescriptor.GetProperties(this, attributes, true); 

    foreach (PropertyDescriptor prop in defaultProperties) 
    { 
     if(!prop.IsReadOnly) 
     { 
      //adds a readonly attribute 
      Attribute[] readOnlyArray = new Attribute[1]; 
      readOnlyArray[0] = new ReadOnlyAttribute(true); 
      TypeDescriptor.AddAttributes(prop,readOnlyArray); 
     } 

     fullList.Add(prop); 
    } 

    return new PropertyDescriptorCollection(fullList.ToArray()); 
} 

這是甚至正確的方式來使用TypeDescriptor.AddAttributes()?在調用之後調試時,AddAttributes()prop仍然具有相同數量的屬性,其中沒有一個是ReadOnlyAttribute。

回答

2

TypeDescriptor.AddAttributes增加類級別屬性給定的對象或對象類型,而不是屬性級別屬性。最重要的是,除了返回的TypeDescriptionProvider的行爲之外,我認爲它沒有任何影響。

相反,我想包所有的默認屬性的描述是這樣的:

public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
{ 
    return new PropertyDescriptorCollection(
     TypeDescriptor.GetProperties(this, attributes, true) 
      .Select(x => new ReadOnlyWrapper(x)) 
      .ToArray()); 
} 

其中ReadOnlyWrapper是這樣一類:

public class ReadOnlyWrapper : PropertyDescriptor 
{ 
    private readonly PropertyDescriptor innerPropertyDescriptor; 

    public ReadOnlyWrapper(PropertyDescriptor inner) 
    { 
     this.innerPropertyDescriptor = inner; 
    } 

    public override bool IsReadOnly 
    { 
     get 
     { 
      return true; 
     } 
    } 

    // override all other abstract members here to pass through to the 
    // inner object, I only show it for one method here: 

    public override object GetValue(object component) 
    { 
     return this.innerPropertyDescriptor.GetValue(component); 
    } 
}