2012-04-29 34 views
1

我在我的應用程序中使用PropertyGrid。我需要在運行時更改自定義數據條件下的某些屬性的可見性和只讀屬性。尋找一個事件,當一個屬性的get被調用時觸發

雖然我沒有找到的東西容易&已經準備好了,我發現了一個解決方法在運行時,如下改變ReadOnlyAttributeBrowsableAttribute屬性:

protected void SetBrowsable(string propertyName, bool value) 
{ 
    PropertyDescriptor property = TypeDescriptor.GetProperties(GetType())[propertyName]; 
    BrowsableAttribute att = (BrowsableAttribute)property.Attributes[typeof(BrowsableAttribute)]; 
    FieldInfo cat = att.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance); 

    if (property.Attributes.Cast<Attribute>().Any(p => p.GetType() == typeof(BrowsableAttribute))) 
     cat.SetValue(att, value); 
} 

protected void SetReadOnly(string propertyName, bool value) 
{ 
    PropertyDescriptor property = TypeDescriptor.GetProperties(GetType())[propertyName]; 
    ReadOnlyAttribute att = (ReadOnlyAttribute)property.Attributes[typeof(ReadOnlyAttribute)]; 
    FieldInfo cat = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 

    if (property.Attributes.Cast<Attribute>().Any(p => p.GetType() == typeof(ReadOnlyAttribute))) 
     cat.SetValue(att, value); 
} 

現在,我的問題是,我應該調用這些方法?是否有任何事件可以爲object調用這些方法?也許通過實現一個接口。

回答

1

除非您編寫屬性,否則在調用屬性獲取時不會觸發內置事件。

當然,如果你寫一個自定義的描述符(PropertyDescriptor的,通常是拴在反射描述作爲裝飾),您可以通過描述僅(數據綁定等)攔截訪問,做任何你想要的 - 但對於任意類型(包括那些你沒有寫的)。

在運行時通過反射設置屬性值不是很好。這主要是因爲TypeDescriptor緩存的意外。如果你打算這樣做,TypeDescriptor.AddAttributes(或類似)是可取的。但是,通過實施自定義模型,您正在嘗試做的更合適。根據在您展示這一點,這可以通過一個或完成:

  • 添加自定義類型轉換器,重寫的GetProperties,和基於數據運行時提供自定義的描述 - 工程主要爲PropertyGrid的
  • 實施ICustomTypeDescriptor在您的對象中實現GetProperties並在運行時根據數據提供自定義描述符 - 適用於大多數控件添加自定義TypeDescriptionProvider並與類型(TypeDescriptor.AddProvider)相關聯,從而提供一個ICustomTypeDescriptor,其行爲如上;這將物體從描述符voodoo中分離出來

這些都很棘手!最簡單的就是TypeConverter選項,因爲你提到了PropertGrid,所以它運行良好。繼承自ExpandableObjectConverter並覆蓋GetProperties,根據需要進行過濾,並根據需要爲只讀文件提供自定義描述符。然後將TypeConverterAttribute附加到您的類型,指定您的自定義轉換器類型。

重點:.NET的這個分支非常複雜,模糊,並且在減少使用。但它的工作。

相關問題