2012-05-07 69 views
7

我想在我的PropertyGrid中顯示一個類的多個實例。這個類看起來是這樣的:PropertyGrid只讀對象級屬性

public class Parameter 
{ 
    [Description("the name")] 
    public string Name { get; set; } 

    [Description("the value"), ReadOnly(true)] 
    public string Value { get; set; } 

    [Description("the description")] 
    public string Description { get; set; } 
} 

我有一個TreeView那類的實例。當我在TreeView中選擇其中一個時,按預期顯示在PropertyGrid中。到目前爲止這麼好,但我想通過以下方式自定義此行爲:

對於每個單個實例,我希望能夠防止用戶修改特定屬性。通過在我的課程中設置ReadOnly(true)(如上例所示),所有Value屬性將在級別上被禁用。

經過一番研究,我發現下面的解決方案,它使我有機會來啓用/禁用特定屬性在運行時:

PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this)["Value"]; 

ReadOnlyAttribute attr = 
     (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)]; 

FieldInfo isReadOnly = attr.GetType().GetField(
     "isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 

isReadOnly.SetValue(attr, false); 

,這個方法工作得很好,但不幸的是也只​​有類級別。這意味着如果我將ValueisReadOnly設置爲false,全部我的Parameter-對象具有Value屬性可寫。但我只想在這一個特定的對象上(因此對象級別)。我真的不想爲讀/寫和只讀屬性創建單獨的類。

由於我運行的想法,你的幫助是非常讚賞:)

提前感謝!

編輯:我需要只讀屬性變灰,所以用戶可以看到它不允許或可能編輯它們。

回答

4

編輯:鏈接的文章已被刪除(我希望只是暫時的)。您可以在How to add property-level Attribute to the TypeDescriptor at runtime?的答案中找到可行的替代方案。基本上你必須添加(在運行時)ReadOnlyAttribute通過TypeDescriptor該屬性。


看看這個古老而美好 article on CodeProject,它包含了很多有用的工具 PropertyGrid

基本上你提供了一個類或委託,用於獲取屬性的屬性。因爲它會通過傳遞要獲取屬性的對象的實例來調用,那麼您將能夠以每個對象爲基礎返回(或不是)ReadOnlyAttribute。馬上申請PropertyAttributesProviderAttribute到你的財產,寫你自己的提供者,並從PropertyAttributes集合基於對象本身(而不是在課堂上)取代屬性

+0

我已閱讀整個文檔,但仍不明白你的想法。你能否給我提供一個小代碼示例以使它更清晰一些?感謝您的時間:) –

+0

請參閱該文章中的*動態用法*段落。簡而言之:將PropertyAttributesProviderAttribute應用於您的屬性,編寫您自己的提供程序,並根據對象本身(而不是該類)從PropertyAttributes集合中替換屬性。 –

+0

正如我在源代碼中可以看到的,這需要使用作者自定義的PropertyGrid實現來使其工作?在我的情況下,我必須使用DLL中的現有PropertyGrid(我不能修改)。 –

1

你可以用一個自定義類型說明符的對象,但我認爲這將是矯枉過正,因爲你必須創建一個新的typedescriptor派生類。

所以,一個簡單的解決辦法是有一個標誌,是這樣的:

public class Parameter 
{ 
    private string thevalue; 

    [Browsable(false)] 
    public bool CanEditValue { get; set; } 

    [Description("the name")] 
    public string Name { get; set; } 

    [Description("the description")] 
    public string Description { get; set; } 

    [Description("the value"), ReadOnly(true)] 
    public string Value { 
     get { return this.thevalue; } 
     set { if (this.CanEditValue) this.thevalue = value; } 
    } 
} 
+0

hello海梅,你的建議與雙重屬性將是可以接受的,因爲它是真的簡單。我試過這個,不幸的是,在setter中檢查不會禁用像ReadOnly(true)這樣的屬性編輯...所以它不會變灰。用戶會認爲它是可改變的,但他們的輸入只會被丟棄。任何其他不太複雜的想法? :) –

+0

恐怕你唯一的選擇是派生一個屬性描述符並實現有條件的IsReadOnly屬性獲取器。 – 2012-05-07 18:07:53