Tengo un PropertyGrid con algunas propiedades de clase vinculadas. Cada propiedad tiene un EditorAttribute
donde definí una clase personalizada para realizar cambios. Mi deseo es hacer que la propiedad de cadena solo se pueda editar a través de esta clase Editor y no editando a través del campo de texto PropertyGrid.
Intenté cambiar su atributo ReadOnly
a true
y luego cambiar este valor dentro de mi clase de editor antes de restablecerlo dentro del método de establecimiento de propiedades con Reflection, pero eso no funciona correctamente ya que el campo de texto permanece en modo de enfoque y todavía puedo hacer cambios. Además, para mí, esto es más una solución alternativa que una solución aceptable.
¿Hay alguna forma de acceder al setter de mi propiedad solo mediante la clase EditorComponent
y no mediante PropertyGrid?
Mi clase de editor personalizado:
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; }
y después de esto lo cambio en mi método 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 } } } }
Puede agregar TypeConverter
adicional que evitará la edición (simplemente descartando cualquier conversión de cadena a tipo de destino (incluso el destino también es una cadena)).
Después de esto, puede eliminar todas las cosas cableadas editando ReadOnlyAttribute
en rutime.
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; } }
Además, es posible que desee agregar una verificación adicional en EditValue
para asegurarse de que el servicio esté disponible, el valor de entrada es una string
real, etc.
También puede invalidar miembros de ReadOnlyConverter
para deshabilitar explícitamente la conversión de cadenas y no depender de la implementación predeterminada.