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