[.NET 4.8] PropertyGridでReadOnlyを動的に変更したい

1 min read読了の目安(約1200字

0. 概要

Name Value
Framework .NET Framework 4.8
Language C#/WinForm

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の組み合わせによって挙動が変わるように見受けられたのですが、すべての組み合わせを検証しなかったため、このような言い回しにしました。