[WinForms] PropertyGridでReadOnlyを個別かつ動的に変更したい

公開:2020/11/11
更新:2020/11/11
1 min読了の目安(約1100字IDEAアイデア記事

0. 概要

PropertyGridで各項目のReadOnlyAttributeをプログラム実行中に変更しようとして、色々検索してみました。

1. 検証

Reflectionを利用してisReadOnlyを変更する方法が散見されたが、それに対する結果がまちまちでした。
少し検証してみたところ、設計時にReadOnlyAttributeを記述しておかないと、想定した挙動にならないことが分かりました。

public class Setting
{  
  [ReadOnly(false)]
  public string Filepath { get; set; }

  public int Value1 { get; set; }

  [ReadOnly(true)]
  public int Value2 { get; set; }

  public void SetReadOnly(string name, bool value)
  {
     var descriptor = TypeDescriptor.GetProperties(GetType())[name];

     var attribute = descriptor.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
     if (attribute != null)
     {
        var fieldInfo = attribute.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
        if (fieldInfo != null)
        {
           fieldInfo.SetValue(attribute, value);
        }
     }
  }
}
var setting = new Setting();

setting.SetReadOnly("Filepath", true);
//setting.SetReadOnly("Value1", true); // 想定通りに動作しない
setting.SetReadOnly("Value2", false);

2. 備考

想定通りに動作しない』という曖昧な言葉を選んだのは、設計時に使用したAttributeの組み合わせによって挙動が変わるように見受けられたのですが、すべての組み合わせを検証しなかったため、このような言い回しにしました。