Необходимо скрыть свойство «Только дизайнер» от PropertyGrid для элемента управления .NET Winforms - PullRequest
1 голос
/ 29 сентября 2019

Я глубоко использую конструктор Winforms (пространство имен System.ComponentModel.Design) в своем решении C # /. NET, чтобы мои пользователи имели доступ к конструктору форм в моем запущенном приложении. Многое из этого работает хорошо, но я столкнулся с очень специфической проблемой: я столкнулся со свойством элемента управления Microsoft, которое появляется только во время разработки, т. Е. Для экземпляра элемента управления во время разработки. Я хочу отключить это свойство, чтобы пользователи не могли изменить его, когда они помещают экземпляр этого элемента управления в реализацию моей программы в области разработки Winform.

Подробности: когда пользователь перетаскивает элемент управления изНа панели инструментов на поверхности конструктора я гарантирую, что выбран вновь добавленный экземпляр конструктора элемента управления (чтобы он представлял маркеры изменения размера и чтобы в сетке свойств отображались свойства этого элемента времени разработки). Я связываю выбранные объекты на поверхности конструктора с сеткой свойств, используя метод GetSelectedComponents () службы выбора и назначая свойству сетки свойств SelectedObjects результат.

Многие элементы управления на моей панели инструментов являются элементами управления .NET. Одним из них является элемент управления .NET Winforms TableLayoutPanel . Когда вы поместите экземпляр этого элемента управления на поверхность конструктора, вы увидите свойство Columns в ограниченном PropertyGrid . Я хотел бы подавить это свойство, чтобы оно не отображалось в PropertyGrid .

Проблема заключается в том, что это свойство столбцов не отображается в списке свойств для TableLayoutPanel type - поэтому использование selectedComponents[0].GetType().GetProperties(), например, не содержит свойства Columns . Кроме того, я не могу создать новое или переопределить существующее свойство Columns , поскольку оно не отображается как открытое свойство для элемента управления TableLayoutPanel во время разработки - поэтому я не могу его украситьс атрибутом Browsable(false).

Кажется, я не могу использовать PreFilterProperties или PostFilterProperties, потому что я не могу взаимодействовать и настраивать конструктор TableLayoutPanel.

Как я могу подавить Столбцы Свойство конструктора для TableLayoutPanel , чтобы оно не отображалось в PropertyGrid без необходимости писать собственный конструктор?

1 Ответ

2 голосов
/ 07 октября 2019

Если вы пытаетесь избежать написания 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, а также глаголы, назначенные для редактирования / добавления / удаления столбцов и строк.

...