Необходимо скрыть свойство только для конструктора из PropertyGrid для элемента управления .NET Winforms

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

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

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

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

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

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

1 ответ

Решение

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

Другие вопросы по тегам