c# - 使属性只能通过绑定(bind)的编辑器(组件)进行编辑

标签 c# .net winforms propertygrid

我有一个 PropertyGrid,其中绑定(bind)了一些类属性。 每个属性都有一个EditorAttribute,我在其中定义了一个自定义类来进行更改。 我的愿望是使字符串属性只能通过此编辑器类进行编辑,而不是通过 PropertyGrid 文本字段进行编辑。

我尝试将其 ReadOnly 属性更改为 true,然后在编辑器类中更改此值,然后使用反射在属性 setter 方法中重置它,但那就是由于文本字段保持焦点模式而无法正常工作,但我仍然可以进行更改。此外,对于我来说,这更像是一种解决方法,而不是可接受的解决方案。

有没有办法仅通过 EditorComponent 类而不是 PropertyGrid 访问我的属性的 setter ?

我的自定义编辑器类:

public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
   using (EditorForm f = new Forms.EditorForm(value.ToString()))
   {
      if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
      {
         PropertyDescriptor descriptor = context.PropertyDescriptor;
         if (descriptor != null)
         {
            ReadOnlyAttribute attribute = descriptor.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
            if (attribute != null)
            {
               System.Reflection.FieldInfo fieldToChange = attribute.GetType().GetField("isReadOnly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
               if (fieldToChange != null)
               {
                  fieldToChange.SetValue(attribute, false); // setting it to false
                  value = f.Text;
               }
            }
         }
      }
   }
   return value;
}

之后我在我的 setter 方法中重新更改它:

private string _myText = String.Empty;
[Editor(typeof(...), typeof(UITypeEditor)),
ReadOnly(true)]
public string MyText
{
   get { return _myText; }
   set
   {
      _myText = value;
      PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this)["MyText"];
      if (descriptor != null)
      {
         ReadOnlyAttribute attribute = descriptor.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
         if (attribute != null)
         {
            System.Reflection.FieldInfo fieldToChange = attribute.GetType().GetField("isReadOnly", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
             if (fieldToChange != null)
                fieldToChange.SetValue(attribute, true); // resetting it to true
         }
      }
    }
}

最佳答案

您可以添加额外的TypeConverter,这将阻止编辑(只需丢弃从字符串到目标类型的任何转换(即使目标也是字符串))。

此后,您可以通过在 rutime 中编辑 ReadOnlyAttribute 来删除所有有线内容。

public class TestClass
{
    [Editor(typeof(CustomEditor), typeof(UITypeEditor))]
    [TypeConverter(typeof(ReadOnlyConverter))]
    public string MyText { get; set; }
}

public class ReadOnlyConverter : TypeConverter
{
    //just empty class
}

public class CustomEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
           => UITypeEditorEditStyle.Modal;

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        var strVal = value as string;
        var svc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

        using (var editorForm = new EditorForm())
        {
            editorForm.Value = strVal;

            svc.ShowDialog(editorForm);
            value = editorForm.Value;
        };
        

        return value;
    }
}

此外,您可能需要在 EditValue 中添加额外检查,以确保服务可用、输入值是真实的字符串等等。

您还可以覆盖 ReadOnlyConverter 的成员以显式禁用字符串转换,而不依赖于默认实现。

关于c# - 使属性只能通过绑定(bind)的编辑器(组件)进行编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71249776/

相关文章:

.net - 基本 CLI 库 'mscorlib' 与引用的 F# 核心库二进制不兼容

winforms - 有没有办法强制 DataGridView 为所有单元格触发其 CellFormatting 事件?

c# - 在 Java 中运行 C# 代码

c# - 无法使用 LINQPad 4 更新行

c# - Dapper 建筑参数表

c# - 单独项目下的 ASP.NET Web API 帮助页面

c# - Spring.NET AOP 代理和 MS WebAPI Controller

c# - ASP .NET 应用程序启动了多少次

c# - Web Api 2 未将 ByteArrayContent 返回给 HTTPClient

c# - 超时正在触发,但应用程序继续正常运行