How can I override behavior of DockStyle Editor in PropertyGrid

二次信任 提交于 2019-12-08 01:36:41

问题


We have a custom panel which inherits Panel and has an Orientation property implemented similarly to the SplitContainer Orientation property. For our custom panel, DockStyle.Fill is never valid and depending on the Orientation property value, DockStyle needs to be Left or Right for Vertical or Top or Bottom for Horizontal.

The DockStyleEditor class is sealed so we can't subclass it for our own custom UITypeEditor. Is there a way to override certain behaviors using a TypeDescriptor or some other way?

What we would like to do for our custom panel DockStyle editor in the Property Grid is:
1. Either disable the center Fill button or display it with the red slash circle to indicate it is unavailable as an option
2. Disable the Top and Bottom buttons when the Orientation property is horizontal
3. Disable the Left and Right buttons when the Orientation property is vertical


回答1:


DockEditor is sealed but you can create your custom dock editor based on DockEditor without inheriting it. In your custom UITypeEditor, you can create an instance of DockEditor and using reflection manipulate its editor control and then perform value editing using it.

The DockEditor uses a DockUI control which is a private class. It has a check box for None button and container control which contains check boxes for Fill, Top, Left, Right and Bottom. Then you can simply change Enabled, BackColor or other properties based on your logic.

In the below code I'll find those check box buttons and I will disable Fill, Top, Bottom and None. The only options available for the user will be Left and Right:

public class MyDockEditor : UITypeEditor
{
    DockEditor editor;
    public MyDockEditor()
    {
        editor = new System.Windows.Forms.Design.DockEditor();
    }
    public override object EditValue(ITypeDescriptorContext context, 
                                     IServiceProvider provider, object value)
    {
        Type dockUiType = typeof(DockEditor)
               .GetNestedType("DockUI", BindingFlags.NonPublic);
        var dockUiConstructor = dockUiType.GetConstructors()[0];
        var dockUiField = typeof(DockEditor)
               .GetField("dockUI", BindingFlags.Instance | BindingFlags.NonPublic);
        var dockUiObject = dockUiConstructor.Invoke(new[] { editor }) as Control;
        dockUiField.SetValue(editor, dockUiObject);
        var container = dockUiObject.Controls[0];
        var none = dockUiObject.Controls[1];
        var fill=  container.Controls[0];
        var left= container.Controls[1];
        var right= container.Controls[2];
        var top = container.Controls[3];
        var bottom = container.Controls[4];
        none.Enabled = false;
        fill.Enabled = false;
        top.Enabled = false;
        bottom.Enabled = false;
        return editor.EditValue(context, provider, value);
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return editor.GetEditStyle(context);
    }
}

To use it it's enough to decorate Dock property of your control with an Editor attribute:

[Editor(typeof(MyDockEditor), typeof(UITypeEditor))]
public override DockStyle Dock
{
    get { return base.Dock; }
    set { base.Dock = value; }
}

As you see in below image, only left and right enabled.



来源:https://stackoverflow.com/questions/36192542/how-can-i-override-behavior-of-dockstyle-editor-in-propertygrid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!