UserControl с заголовком и содержимым - разрешить удаление элементов управления на панели данных и запретить удаление элементов управления в заголовке во время разработки.

avatar
Thaven
8 июня 2018 в 10:54
1011
1
6

Я написал User Control (ура!). Но я хочу, чтобы он вел себя как контейнер. Но ждать! Я знаю о

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", 
    typeof(IDesigner))]

Уловка.

Проблема в том, что я не хочу, чтобы весь мой элемент управления вел себя как контейнер, а только одна его часть. Одна - де-факто - панель;)

Для более широкого контекста: я написал элемент управления с сеткой, некоторыми общими кнопками, ярлыками и функциями. Но у него также есть часть, где пользователь должен оставлять свои настраиваемые кнопки / элементы управления, что угодно. Только в этой части управления, больше нигде.

Кто-нибудь знал?

Источник
GuidoG
8 июня 2018 в 11:07
1

Я не знаком с пользовательскими элементами управления, но не можете ли вы просто поместить панель в область, где вы хотите, чтобы пользователь мог размещать элементы управления? Возможно, вам также нужно изменить свойство modifier этой панели

Thaven
8 июня 2018 в 11:48
0

@GuidoG - к сожалению, нет :(. Модификатор работает нормально при наследовании, но, насколько я пытался, нет способа сделать таким образом "редактируемость" компонента из пользовательского контроля.

GuidoG
8 июня 2018 в 11:50
0

это, вероятно, снова причина того, почему я никогда не использую пользовательские элементы управления, а наследую непосредственно от того, что мне нужно, или от Panel

Ответы (1)

avatar
Reza Aghaei
9 июня 2018 в 08:58
7

Вам необходимо сделать следующее:

  • Для вашего пользовательского элемента управления вам необходимо создать новый дизайнер, который активирует внутреннюю панель во время разработки, вызвав метод EnableDesignMode.
  • Для внутренней панели вам необходимо создать дизайнер, который отключает перемещение, изменение размера и удаляет некоторые свойства из дизайнера.
  • Вы должны зарегистрировать дизайнеров.

Пример

Вы можете прочитать сообщение в блоге по этой теме здесь и клонировать или загрузить рабочий пример:

enter image description here

Код

Вот коды для различных элементов решения.

Ваш пользовательский элемент управления

[Designer(typeof(MyUserControlDesigner))]
public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        TypeDescriptor.AddAttributes(this.panel1,
            new DesignerAttribute(typeof(MyPanelDesigner)));
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Panel ContentsPanel
    {
        get { return panel1; }
    }
}

Конструктор внутренней панели

public class MyPanelDesigner : ParentControlDesigner
{
    public override SelectionRules SelectionRules
    {
        get
        {
            SelectionRules selectionRules = base.SelectionRules;
            selectionRules &= ~SelectionRules.AllSizeable;
            return selectionRules;
        }
    }
    protected override void PostFilterAttributes(IDictionary attributes)
    {
        base.PostFilterAttributes(attributes);
        attributes[typeof(DockingAttribute)] = 
            new DockingAttribute(DockingBehavior.Never);
    }
    protected override void PostFilterProperties(IDictionary properties)
    {
        base.PostFilterProperties(properties);
        var propertiesToRemove = new string[] {
            "Dock", "Anchor", "Size", "Location", "Width", "Height",
            "MinimumSize", "MaximumSize", "AutoSize", "AutoSizeMode",
            "Visible", "Enabled",
        };
        foreach (var item in propertiesToRemove)
        {
            if (properties.Contains(item))
                properties[item] = TypeDescriptor.CreateProperty(this.Component.GetType(),
                    (PropertyDescriptor)properties[item],
                    new BrowsableAttribute(false));
        }
    }
}

Конструктор для вашего пользовательского элемента управления

public class MyUserControlDesigner : ParentControlDesigner
{
    public override void Initialize(IComponent component)
    {
        base.Initialize(component);
        var contentsPanel = ((MyUserControl)this.Control).ContentsPanel;
        this.EnableDesignMode(contentsPanel, "ContentsPanel");
    }
    public override bool CanParent(Control control)
    {
        return false;
    }
    protected override void OnDragOver(DragEventArgs de)
    {
        de.Effect = DragDropEffects.None;
    }
    protected override IComponent[] CreateToolCore(ToolboxItem tool, int x,
        int y, int width, int height, bool hasLocation, bool hasSize)
    {
        return null;
    }
}
Jazimov
1 февраля 2020 в 21:02
0

Реза, я хотел, чтобы это сработало для меня, когда я впервые обнаружил ваш пост. попытался применить этот пример к TableLayoutPanel. Когда я изменил тип панели содержимого с Panel на TableLayoutPanel (TLP) и протестировал, я потерял функции времени разработки для панели макета, когда я перетащил пользовательский элемент управления на поверхность дизайна. Например, я увидел свойство Columns, когда выбрал элемент управления ContentsPanel, но когда я изменил его с 0, скажем, на 2, столбцы не отображаются в экземпляре конструктора элемента управления. Я также не мог получить доступ к более продвинутым свойствам TLP (например, метрикам строк / столбцов).

Reza Aghaei
1 февраля 2020 в 21:05
1

@Jazimov Я думаю, что это не будет работать для TableLayouPanel из-за некоторых ограничений TableLayoutPanel.

Jazimov
1 февраля 2020 в 21:07
1

Ах, такова жизнь. :) Я все еще доволен вашим Решением 2 на вопрос coderhelper.com/questions/59965679/…. Я надеюсь, что другие могут извлечь выгоду из этого подхода.