Добавление элементов управления на панель в пользовательском элементе управления в конструкторе - PullRequest
0 голосов
/ 28 августа 2018

У меня есть особое требование для создания пользовательского элемента управления с определенными общими функциями. Для этого элемента управления у меня также есть требование разрешить другим разработчикам добавлять элементы управления в режиме конструктора для создания определенных пользовательских интерфейсов. Для этого я создал пользовательский элемент управления, добавив (образец) метку и кнопку. Я также добавил панель, чтобы разрешить добавление дополнительных элементов управления в определенной области элемента управления.

Затем я сделал класс видимым в режиме конструктора, добавив разметку [Designer] и [ControlDesigner]. Это дает желаемый эффект добавления пользовательского элемента управления с некоторым фиксированным содержимым и добавления дополнительных элементов управления на страницу. Проблема в том, что пользователь может переместить панель в режиме разработки, и VisualStudio запутается, создав круговую ссылку. Я что-то упустил? Можно ли отключить изменение размера / расположения панели, даже если мне нужен режим дизайна?

ПРИМЕЧАНИЕ. Я также пытался использовать пользовательский элемент управления в режиме разработки, но добавленные элементы управления продолжают исчезать за фиксированными элементами управления в пользовательском элементе управления.

Код и примеры приведены ниже. Любые предложения / исправления приветствуются.

Над изображением пользовательского элемента управления с панелью

enter image description here

Выше приведена форма, включающая пользовательский элемент управления и добавление настраиваемой кнопки на панель. Обратите внимание, что при перетаскивании панели включается, при касании в файле form.designer.cs создается круговая ссылка, и проект становится неустойчиво.

Наконец, ниже приведен класс для пользовательского управления

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

using System.Windows.Forms.Design;

namespace wfcLib
{

    [DesignerAttribute(typeof(MyControlDesigner))]
    [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
    public partial class ucInput : UserControl
    {

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Panel InternalPanel
        {
            get { return pnlContent; }
            set { pnlContent = value; }
        }
        public ucInput()
        {
            InitializeComponent();

        }

    }
    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    public class MyControlDesigner : System.Windows.Forms.Design.ControlDesigner
    {
        public override void Initialize(IComponent c)
        {
            base.Initialize(c);
            ucInput ctl = (ucInput)c;
            EnableDesignMode(ctl.InternalPanel, "InternalPanel");
        }
    }
}

1 Ответ

0 голосов
/ 28 августа 2018

В дополнение к моему комментарию, касающемуся использования производного Panel с его собственным конструктором, который переопределяет свойство SelectionRules, другим методом будет использование ISelectionService дизайнера для обнаружения изменений в выбранных компонентах. и удалите панель, если она была выбрана.

Это достигается путем переопределения свойства Site элемента управления для установки ловушки. Также обратите внимание, что я изменил свойство InternalPanel только для чтения, так как вы действительно не хотите, чтобы это было доступно для записи.

[DesignerAttribute(typeof(MyControlDesigner))]
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ucInput : UserControl
{

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Panel InternalPanel
    {
        get { return pnlContent; }
    }

    public ucInput()
    {
        InitializeComponent();
    }

    private ISelectionService selectionService;
    private IDesignerHost host;
    public override ISite Site
    {
        get
        {
            return base.Site;
        }
        set
        {
            host = null;
            UnSubscribeFromSelectionService();
            base.Site = value;
            if (value != null)
            {
                host = (IDesignerHost)this.Site.GetService(typeof(IDesignerHost));
                if (host != null)
                {
                    if (host.Loading)
                    {
                        // defer subscription to selection service until fully loaded
                        host.Activated += Host_Activated;
                    }
                    else
                    {
                        SubscribeToSelectionService();
                    }
                }
            }
        }
    }

    private void Host_Activated(object sender, EventArgs e)
    {
        host.Activated -= Host_Activated;
        SubscribeToSelectionService();
    }

    private void SubscribeToSelectionService()
    {
        selectionService = (ISelectionService)this.Site.GetService(typeof(ISelectionService));
        if (selectionService != null)
        {
            selectionService.SelectionChanging += OnSelectionChanging;
        }
    }

    private void UnSubscribeFromSelectionService()
    {
        if (selectionService != null)
        {
            selectionService.SelectionChanging -= OnSelectionChanging;
        }
    }

    private void OnSelectionChanging(object sender, EventArgs e)
    {
        if (selectionService.GetComponentSelected(pnlContent))
        {
            selectionService.SelectionChanging -= OnSelectionChanging;
            selectionService.SetSelectedComponents(new[] { pnlContent }, SelectionTypes.Remove);
            selectionService.SelectionChanging += OnSelectionChanging;
        }
    }
}

Редактировать: Исходный код, пренебрегаемый для учета SelectionService, недоступен, пока загружается IDesignerHost. Добавлен код для отсрочки подписки до активации IDesignerHost.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...