使 属性 只能通过绑定的编辑器(组件)进行编辑
Make a property only editable through the bound Editor(component)
我有一个 PropertyGrid,其中绑定了一些 class-properties。
每个 属性 都有一个 EditorAttribute
,我在其中定义了一个自定义 class 来进行更改。
我的愿望是使字符串-属性 只能通过此编辑器-class 进行编辑,而不能通过 PropertyGrid-文本字段进行编辑。
我尝试将其 ReadOnly
-属性更改为 true
,然后在我的编辑器中更改此值-class,然后在属性 setter-方法中重置它反射,但由于文本字段处于焦点模式而无法正常工作,我仍然可以进行更改。此外,对于我来说,这更像是一种解决方法,而不是可接受的解决方案。
有没有办法只通过 EditorComponent
-class 而不是通过 PropertyGrid 访问我的 属性 的 setter?
我的自定义编辑器-class:
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
中添加检查以确保服务可用、输入值是真实的 string
等等。
您还可以覆盖 ReadOnlyConverter
的成员以显式禁用字符串转换而不依赖于默认实现。
我有一个 PropertyGrid,其中绑定了一些 class-properties。
每个 属性 都有一个 EditorAttribute
,我在其中定义了一个自定义 class 来进行更改。
我的愿望是使字符串-属性 只能通过此编辑器-class 进行编辑,而不能通过 PropertyGrid-文本字段进行编辑。
我尝试将其 ReadOnly
-属性更改为 true
,然后在我的编辑器中更改此值-class,然后在属性 setter-方法中重置它反射,但由于文本字段处于焦点模式而无法正常工作,我仍然可以进行更改。此外,对于我来说,这更像是一种解决方法,而不是可接受的解决方案。
有没有办法只通过 EditorComponent
-class 而不是通过 PropertyGrid 访问我的 属性 的 setter?
我的自定义编辑器-class:
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
中添加检查以确保服务可用、输入值是真实的 string
等等。
您还可以覆盖 ReadOnlyConverter
的成员以显式禁用字符串转换而不依赖于默认实现。