如何覆盖 PropertyGrid 中 DockStyle Editor 的行为

How can I override behavior of DockStyle Editor in PropertyGrid

我们有一个自定义面板,它继承了 Panel 并具有类似于 SplitContainer 方向 属性 实现的方向 属性。对于我们的自定义面板,DockStyle.Fill 永远无效,并且根据方向 属性 值,DockStyle 需要为垂直的左或右或水平的顶部或底部。

DockStyleEditor class 是密封的,因此我们无法将其子class 用于我们自己的自定义 UITypeEditor。有没有办法使用 TypeDescriptor 或其他方式覆盖某些行为?

我们想为 属性 网格中的自定义面板 DockStyle 编辑器做的是:
1. 要么禁用中间的填充按钮,要么用红色斜线圆圈显示它,以表明它作为一个选项不可用
2. 当 Orientation 属性 为 horizo​​ntal
时禁用 Top 和 Bottom 按钮 3. 当 Orientation 属性 为垂直

时禁用 Left 和 Right 按钮

DockEditor is sealed but you can create your custom dock editor based on DockEditor without inheriting it. In your custom UITypeEditor,你可以创建一个DockEditor的实例,并使用反射操作它的编辑器控件,然后使用它进行值编辑。

DockEditor 使用一个 DockUI 控件,它是私有的 class。它有一个 None 按钮和容器控件的复选框,其中包含 FillTopLeftRightBottom 的复选框。 然后你可以根据你的逻辑简单地更改 EnabledBackColor 或其他属性。

在下面的代码中,我将找到那些复选框按钮,我将禁用 FillTopBottomNone。用户可用的唯一选项是 LeftRight:

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);
    }
}

要使用它,只需使用编辑器属性装饰 Dock 属性 控件即可:

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

如下图所示,只启用了左右。