为了账号安全,请及时绑定邮箱和手机立即绑定

需要从 .NET Winforms 控件的 PropertyGrid 中隐藏仅设计器属性

需要从 .NET Winforms 控件的 PropertyGrid 中隐藏仅设计器属性

PHP
富国沪深 2024-01-20 21:38:14
我深入研究在我的 C#/.NET 解决方案中使用 Winforms 设计器(System.ComponentModel.Design 命名空间),以便我的用户可以在我正在运行的应用程序中访问表单设计器。其中大部分工作正常,但我遇到了一个非常具体的问题:我遇到了 Microsoft 控件上的一个属性,该属性仅在设计时出现,即针对该控件的设计时实例。我想抑制该属性,以便用户在将该控件的实例放置在我的程序的 Winform 设计图面实现上时无法修改它。详细信息:当用户将控件从工具箱拖放到设计器表面时,我确保选择新添加的控件的设计器实例(以便它显示调整大小手柄,并且属性网格显示该控件的设计-时间属性)。我通过使用选择服务的GetSelectedComponents()方法并将属性网格的SelectedObjects属性分配给结果,将设计器表面上的选定对象绑定到属性网格。我的工具箱中的许多控件都是 .NET 控件。其中之一是 .NET Winforms TableLayoutPanel控件。当您将该控件的实例放置在设计器图面上时,您将在绑定的PropertyGrid中看到Columns属性。我想禁止该属性,以便它不会出现在PropertyGrid中。问题在于, TableLayoutPanel类型的属性列表中似乎不存在此 Columns 属性,因此,例如, usingselectedComponents[0].GetType().GetProperties()不包含Columns属性。另外,我无法为现有的Columns属性创建新属性或覆盖它,因为它在设计时不会显示为TableLayoutPanelBrowsable(false)控件的公开属性,因此我无法使用该属性来装饰它。我似乎无法利用PreFilterProperties或PostFilterProperties因为我无法交互和自定义TableLayoutPanel 的设计器。如何抑制TableLayoutPanel的Columns设计器属性,使其不会出现在PropertyGrid中,而无需编写自己的设计器?
查看完整描述

1 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

如果您试图避免TableLayoutPanelDesigner自己编写,那么我可以建议您使用以下解决方法。

ITypeDescriptorFilterService是负责调用PreFilterProperties设计器方法的接口。该类DesignSurface在其ServiceContainer. 因此,您可以删除现有的已注册实例并注册您自己的ITypeDescriptorFilterService.

在新的实现中,重写FilterProperties并执行您认为合适的任何操作,例如您可以检查组件的类型是否为TableLayoutPanel,然后不要调用其设计器PreFilterProperties

然后,为了总结解决方案,您需要通过从DesignSurface类派生并删除已注册ITypeDescriptorFilterService并注册您创建的所需实例来创建自己的设计界面。

例子

仅供您参考,您正在查找的属性的名称是ColumnStyles,并且默认情况下具有Browsable(false)属性。但默认的设计者TableLayoutPanel用可浏览的版本替换了这个属性。

我在这个例子中所做的就是阻止设计者使这些属性可见。

首先提供ITypeDescriptorFilterService. 下面的一个实际上是System.Design汇编中的现有实现,我更改了它的FilterProperties方法并检查了组件是否是TableLayoutPanel,我要求什么也不做。

using System;

using System.Collections;

using System.ComponentModel;

using System.ComponentModel.Design;

using System.Windows.Forms;

public class TypeDescriptorFilterService : ITypeDescriptorFilterService

{

    internal TypeDescriptorFilterService()

    {

    }


    private IDesigner GetDesigner(IComponent component)

    {

        ISite site = component.Site;

        if (site != null)

        {

            IDesignerHost service = site.GetService(typeof(IDesignerHost)) as IDesignerHost;

            if (service != null)

                return service.GetDesigner(component);

        }

        return (IDesigner)null;

    }


    bool ITypeDescriptorFilterService.FilterAttributes(IComponent component, IDictionary attributes)

    {

        if (component == null)

            throw new ArgumentNullException("component");

        if (attributes == null)

            throw new ArgumentNullException("attributes");

        IDesigner designer = this.GetDesigner(component);

        if (designer is IDesignerFilter)

        {

            ((IDesignerFilter)designer).PreFilterAttributes(attributes);

            ((IDesignerFilter)designer).PostFilterAttributes(attributes);

        }

        return designer != null;

    }


    bool ITypeDescriptorFilterService.FilterEvents(IComponent component, IDictionary events)

    {

        if (component == null)

            throw new ArgumentNullException("component");

        if (events == null)

            throw new ArgumentNullException("events");

        IDesigner designer = this.GetDesigner(component);

        if (designer is IDesignerFilter)

        {

            ((IDesignerFilter)designer).PreFilterEvents(events);

            ((IDesignerFilter)designer).PostFilterEvents(events);

        }

        return designer != null;

    }


    bool ITypeDescriptorFilterService.FilterProperties(IComponent component, IDictionary properties)

    {

        if (component == null)

            throw new ArgumentNullException("component");

        if (properties == null)

            throw new ArgumentNullException("properties");

        if (typeof(TableLayoutPanel).IsAssignableFrom(component.GetType()))

            return true;

        IDesigner designer = this.GetDesigner(component);

        if (designer is IDesignerFilter)

        {

            ((IDesignerFilter)designer).PreFilterProperties(properties);

            ((IDesignerFilter)designer).PostFilterProperties(properties);

        }

        return designer != null;

    }

}

然后通过派生创建一个设计图面DesignSurface:


using System;

using System.Collections;

using System.ComponentModel;

using System.ComponentModel.Design;

using System.Windows.Forms;

public class MyDesignSurface : DesignSurface

{

    public MyDesignSurface() : base()

    {

        this.ServiceContainer.RemoveService(typeof(ITypeDescriptorFilterService));

        this.ServiceContainer.AddService(typeof(ITypeDescriptorFilterService), new TypeDescriptorFilterService());

    }

}

然后例如以这种方式初始化设计图面:


public partial class Form1 : Form

{

    public Form1()

    {

        InitializeComponent();

        var surface = new MyDesignSurface();

        var host = (IDesignerHost)surface.GetService(typeof(IDesignerHost));

        var selectionService = (ISelectionService)surface.GetService(typeof(ISelectionService));

        surface.BeginLoad(typeof(Form));

        var root = (Form)host.RootComponent;

        var tableLayoutPanel1 = (Control)host.CreateComponent(typeof(TableLayoutPanel), "tableLayoutPanel1");

        root.Controls.Add(tableLayoutPanel1);

        var view = (Control)surface.View;

        view.Dock = DockStyle.Fill;

        this.Controls.Add(view);

        selectionService.SetSelectedComponents(new[] { tableLayoutPanel1 });

        var propertyGrid1 = new PropertyGrid() { Dock = DockStyle.Right, Width = 200 };

        this.Controls.Add(propertyGrid1);

        propertyGrid1.SelectedObjects = selectionService.GetSelectedComponents().Cast<object>().ToArray();

    }

}

然后运行您的设计器应用程序,您将看到Columns属性Rows按预期隐藏。


您需要隐藏ColumnCount属性RowCount以及分配给编辑/添加/删除列和行的动词。


查看完整回答
反对 回复 2024-01-20
  • 1 回答
  • 0 关注
  • 161 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信