以下に示すように、一連のプロパティを持つクラスがあります。
class ContactInfo
{
[ReadOnly(true)]
[Category("Contact Info")]
public string Mobile { get; set; }
[Category("Contact Info")]
public string Name{ get; set; }
}
このクラスのオブジェクトはプロパティグリッドに割り当てられているため、ユーザーは既存の連絡先を更新できます。モバイルが読み取り専用としてマークされていることがわかります。
ただし、まったく新しい連絡先を追加する場合は、ユーザーが連絡先モバイルも編集できるようにする必要があります。そのためには、オブジェクトをプロパティグリッドに割り当てる前に、タイプから読み取り専用プロパティを動的に削除するする必要があります。出来ますか?
実行時に属性を削除することはできませんが、リフレクションを使用して、ReadOnly属性のReadOnlyプライベートバッキングフィールドをFalseに変更できます。 [ReadOnly(false)]と同等にします
詳細については、この記事を参照してください。
http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html
編集:固定リンク
Omuと同意する必要があります。この場合、2つの異なるビューをサポートするために、実際には2つのクラス(ビューモデル)について話していることになります。何かのようなもの
CreateContactViewModelおよびEditContactViewModel
現時点では、属性を動的に削除することはできません(実行時)
提案として、2つのクラスを実行できます。1つは属性あり、もう1つは属性なしです。
CodingLight.comブログがblogspotに移動しました(上記のリンクは壊れています)。 http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html を参照してください。
さらに、SysAdminのフォローアップでは、実際に機能するソリューションに必要と思われる[RefreshProperties(RefreshProperties.All)]
属性については言及されていませんでした。
最後に、David Morton(引用された記事の著者)でさえ、1つの非常に重要なことを見逃したと思います:クラス(ContactInfo
、SysAdminのフォローアップの例では)にatがない場合コンパイル時に[ReadOnly]
属性が定義された少なくとも1つのプロパティで、実行時に「isReadOnly」FieldInfoがtrueに設定されると、結果はクラス全体が読み取り専用になります。
Legendenの提案をフォローアップしました。これが私が思いついたものです
class ContactInfo
{
[ReadOnly(true)]
[Category("Contact Info")]
public string Mobile { get; set; }
[Category("Contact Info")]
public string Name{ get; set; }
public void SetMobileEdit(bool allowEdit)
{
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["Mobile"];
ReadOnlyAttribute attrib = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];
FieldInfo isReadOnly = attrib.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
isReadOnly.SetValue(attrib, !allowEdit);
}
}